{% extends "base.html" %} {% from "_macros.html" import wf_badge, export_links with context %} {% block title %}{{ p.code }}{% endblock %} {% block content %} {% set cur = p.currency %} {% set stcls = {'active': 'posted', 'on_hold': 'warn', 'closed': 'cancelled'} %} {% macro meter(pct) %}{% if pct is not none %}
{% endif %}{% endmacro %}
{{ t('Projects') }}

{{ p.code }} — {{ nm(p) }} {{ t(states[p.state]) }}

{{ p.bcode }}{% if p.cust_en %} · {{ nm({'name_en': p.cust_en, 'name_ar': p.cust_ar}) }}{% endif %}{% if p.manager %} · {{ t('Manager') }}: {{ p.manager }}{% endif %}{% if p.start_date %} · {{ p.start_date }} → {{ p.end_date or '…' }}{% endif %} · {{ t('Cost Centre') }} {{ p.cc_code }}
{% if can_write %} {% if p.state == 'active' %} {% if has('procurement') %}+ {{ t('Material Request') }} + {{ t('Purchase Order') }}{% endif %} + {{ t('Vendor Bill') }} {% endif %} {{ t('Edit') }}
{% if p.state == 'active' %} {% else %}{% endif %}
{% endif %}
{{ t('Contract value') }}{{ icon('file') }}
{{ p.contract_value|money(cur) }}{{ cur }}
{% if s.progress_pct is not none %}{{ s.progress_pct }}% {{ t('billed by milestones') }}{% else %}{{ t('No contract value set') }}{% endif %}
{{ t('Budget used') }}{{ icon('target') }}
{{ (s.committed + s.actual)|money(cur) }}{{ cur }}
{{ t('of') }} {{ s.budget|money(cur) }}{% if s.used_pct is not none %} · {{ s.used_pct }}%{% endif %} · {{ t('Remaining') }} {{ s.remaining|money(cur) }}
{{ t('Invoiced to customer') }}{{ icon('receipt') }}
{{ s.billed|money(cur) }}{{ cur }}
{{ t('Still to bill') }} {{ s.to_bill|money(cur) }}
{{ t('Retention held') }}{{ icon('lock') }}
{{ s.retention_balance|money(cur) }}{{ cur }}
{{ p.retention_pct|float }}% · {{ t('released') }} {{ s.retention_released|money(cur) }}
{{ t('Profit to date') }}{{ icon('chart') }}
{{ s.margin|money(cur) }}{{ cur }}
{{ t('Revenue') }} {{ s.revenue|money(cur) }} − {{ t('Cost') }} {{ s.actual|money(cur) }}{% if s.margin_pct is not none %} · {{ s.margin_pct }}%{% endif %}

{{ t('Budget vs committed vs actual') }} ({{ cur }}, {{ t('excl. VAT') }})

{{ export_links() }}
{% for r in rep.rows %} {% else %}{% endfor %} {% if rep.rows %}{% endif %}
{{ t('Account') }}{{ t('Description') }}{{ t('Budget') }}{{ t('Committed') }}{{ t('Actual cost') }}{{ t('Remaining') }}{{ t('Used') }}
{% if r.unbudgeted %}{{ t(r.name_en) }}{% else %}{{ r.code }} {{ nm(r) }}{% endif %}{{ r.description or '' }} {{ r.budget|money(cur, True) }}{{ r.committed|money(cur, True) }}{{ r.actual|money(cur, True) }} {{ r.remaining|money(cur) }}{{ meter(r.used_pct) }}{% if r.used_pct is not none %}{{ r.used_pct }}%{% endif %}
{{ t('No budget yet.') }} {% if can_write %}{{ t('Add budget lines') }}{% endif %}
{{ t('Total') }}{{ rep.total.budget|money(cur) }}{{ rep.total.committed|money(cur) }}{{ rep.total.actual|money(cur) }}{{ rep.total.remaining|money(cur) }}{{ meter(rep.total.used_pct) }}{% if rep.total.used_pct is not none %}{{ rep.total.used_pct }}%{% endif %}

{{ t('Committed = confirmed purchase orders not yet billed. Actual = costs posted to the project’s cost centre. Remaining = Budget − Committed − Actual.') }} {{ t('Budget control') }}: {{ t(controls[p.budget_control]) }}.

{{ t('Milestones (progress billing)') }}

{% for m in milestones %} {% else %}{% endfor %}
{{ t('Milestone') }}{{ t('Due date') }}{{ t('Amount') }}{{ t('Retention') }}{{ t('Status') }}
{{ m.name }}{{ m.due_date or '' }}{% if m.due_date and m.due_date < today and not m.billed %} {{ t('Due') }}{% endif %} {{ m.amount|money(cur) }}{{ ((m.amount * (p.retention_pct or 0) / 100)|round|int)|money(cur, True) }} {% if m.billed %}{{ t('Invoiced') }} {{ m.inv.number or t('Draft') }} {% elif m.state in ('done', 'invoiced') %}{{ t('Completed — to bill') }}{% else %}{{ t('Planned') }}{% endif %} {% if can_write and not m.billed and p.state != 'closed' %} {% if m.state == 'planned' %}
{% endif %}
{% endif %}
{{ t('No milestones yet.') }}
{% if can_write and s.retention_balance - s.release_pending > 0 %}
{{ t('Release retention') }} {{ t('Available') }}: {{ (s.retention_balance - s.release_pending)|money(cur) }} {{ cur }}
{% endif %}

{{ t('Purchasing') }}

{% for d in docs.mr %}{% endfor %} {% for d in docs.pr %}{% endfor %} {% for d in docs.rfq %}{% endfor %} {% for d in docs.po %}{% endfor %} {% if not (docs.mr or docs.pr or docs.rfq or docs.po) %}{% endif %}
{{ t('Material Request') }}{{ d.number }}{{ d.date }}{{ wf_badge(d.state) }}
{{ t('Purchase Requisition') }}{{ d.number }}{{ d.date }}{{ wf_badge(d.state) }}
RFQ{{ d.number }}{{ d.date }}{{ wf_badge(d.state) }}
{{ t('Purchase Order') if d.kind == 'purchase' else t('Sales Order') }}{{ d.number }}
{{ nm({'name_en': d.name_en, 'name_ar': d.name_ar}) }}
{{ d.date }}{{ t(d.state.replace('_', ' ').capitalize()) }}{{ d.amount_untaxed|money(cur) }}
{{ t('Nothing yet.') }}

{{ t('Invoices and bills') }}

{% for d in docs.inv %} {% else %}{% endfor %}
{{ t({'out_invoice': 'Customer Invoice', 'out_refund': 'Customer Credit Note', 'in_invoice': 'Vendor Bill', 'in_refund': 'Vendor Refund'}[d.kind]) }}{% if d.project_billing %}
{{ t('Progress invoice') if d.project_billing == 'progress' else t('Retention release') }}{% endif %}
{{ d.number or t('Draft') }}
{{ nm({'name_en': d.name_en, 'name_ar': d.name_ar}) }}
{{ d.date }} {{ t(d.state.capitalize()) }}{{ d.amount_total|money(cur) }}
{{ t('Nothing yet.') }}

{{ t('Team') }}

{% if p.manager %}{{ p.manager }} · {{ t('Project manager') }}{% endif %} {% for m in members %}{{ m.full_name or m.username }}{% if m.role %} · {{ m.role }}{% endif %} {% endfor %} {% if not p.manager and not members %}{{ t('No team members yet.') }}{% endif %} {% if p.site_address %}

{{ t('Site address') }}: {{ p.site_address }}

{% endif %} {% if p.notes %}

{{ p.notes }}

{% endif %}
{% if units and (units.by_state or units.mos) %}

{{ t('Units for this project') }}

{% set order = [('finished', 'In factory'), ('dispatched', 'Dispatched'), ('delivered', 'Delivered on site'), ('installed', 'Installed'), ('handed_over', 'Handed over'), ('on_rent', 'On rent')] %} {% set total = units.by_state.values()|sum %}
{% for k, l in order %}
{{ t(l) }}
{{ units.by_state.get(k, 0) }}
{% endfor %}
{% if total %}
{{ units.by_state.get('handed_over', 0) }} / {{ total }} {{ t('handed over') }}{% endif %} {% if units.mos %}{% for m in units.mos %}{% endfor %}
{{ t('Production order') }}{{ t('Product') }}{{ t('Quantity') }}{{ t('Status') }}
{{ m.number }}{{ nm(m) }}{{ '%g' % (m.qty_produced if m.state == 'done' else m.quantity) }}{{ t(m.state|replace('_', ' ')|capitalize) }}
{% endif %}
{% endif %} {% endblock %}