@php $steps = [ 'source' => __('Upload'), 'configure' => __('Map columns'), 'preview' => __('Review'), 'done' => __('Done'), ]; $order = ['source', 'configure', 'preview', 'done']; $currentIndex = array_search($stage, $order, true); $statusBadge = [ 'DRAFT' => 'slate', 'SENT' => 'sky', 'PARTIAL' => 'amber', 'PAID' => 'emerald', 'OVERDUE' => 'rose', 'VOID' => 'slate', ]; @endphp
{{ __('CSV template') }} {{-- ======================= STEP 1: SOURCE ======================= --}} @if ($stage === 'source')

{{ __('What are you importing?') }}

@if ($sourceType === 'spreadsheet')
{{ __('Reading file…') }}
@if ($upload && $headers !== [])

{{ __('File read, :n columns detected.', ['n' => count($headers)]) }}

@endif {{-- Or load straight from a shared Google Sheet --}}

{{ __('…or load from Google Sheets') }}

{{ __('Paste a shared Google Sheet link to pull it in directly, then pick the tab and map columns as usual.') }}

{{ __('Load sheet') }} {{ __('Pulling…') }}
@if ($spreadsheetPath && $headers !== [])

{{ __('Google Sheet loaded, :n columns detected.', ['n' => count($headers)]) }}

@endif

{{ __('The sheet must be shared as “Anyone with the link → Viewer”.') }}

@if ($sheetPerJob)
@endif

{{ __('What gets created') }}

{{ __('Each row is one line item. Rows are grouped into documents (by document number, customer + date, or one per row) and each becomes a Customer → Invoice → Job, with Products created from any new item names.') }}

{{ __('On the next step you map your columns, only Item Name is required; Date, Customer, Qty, Unit Price, Status, Currency and discounts are optional.') }} {{ __('Download the CSV template (top-right) for the exact column layout.') }}

{{ __('Got a workbook where each tab is a single job, like the "April costing" sheets, with one Item / Qty / Rate / Discount / Total table per tab? Tick the box above; the tab name becomes the customer and costing-only tabs are skipped.') }}

@elseif ($sourceType === 'pnl') {{-- Shared options (used by both the live sync and a file upload) --}}
@if (count($sheetNames) > 1) @else @endif

{{ __('Tab holding the monthly P&L ledger.') }}

{{ __('Calendar year the month columns belong to.') }}

@if ($recordPayments) @endif
{{-- Live sync from Google Sheets --}}

{{ __('Sync live from Google Sheets') }}

{{ __('keeps records in sync') }}

{{ __('Pulls the latest from the live sheet: new rows are added, changed rows are updated in place, and rows deleted from the sheet are removed, nothing is duplicated.') }}

{{ __('Sync now') }} {{ __('Pulling…') }}

{{ __('The sheet must be shared as “Anyone with the link → Viewer”. Paste the full URL or just the sheet ID.') }}

{{-- Or import a one-off file --}}
{{ __('Reading file…') }}

{{ __('A file import only adds new rows (existing ones are skipped). Use the live sync to also update changed rows.') }}

{{ __('What gets created') }}

{{ __('Each job → customer, invoice (revenue treated as collected), completed job, and production-cost lines routed to the right cost bucket by their COA code. Each month → operating-cost lines filed under the matching expense category, with director-funded overheads recorded as repayable director loans.') }}

@elseif ($sourceType === 'products') {{-- Load the costing workbook from Google or an .xlsx file --}}

{{ __('Load the costing workbook from Google Sheets') }}

{{ __('Paste the shared link to your "Semita Print Costing" workbook, then choose which tabs to import.') }}

{{ __('Load sheet') }} {{ __('Pulling…') }}

{{ __('The sheet must be shared as “Anyone with the link → Viewer”.') }}

{{ __('Reading workbook…') }}
{{-- Per-tab selection (only tabs found in the workbook) --}} @if ($productsSections !== []) @php $sectionMeta = $this->productSectionMeta(); @endphp

{{ __('Which sheets to import') }}

{{ __(':n importable tab(s) found', ['n' => count($productsSections)]) }}

@foreach ($productsSections as $key) @endforeach

{{ __('Tiers & retail details attach to products by name, they\'ll match products from this import or a previous one. Re-running updates existing records.') }}

{{ __('Import selected') }} {{ __('Importing… (this can take a moment)') }}
@endif

{{ __('What gets created') }}

{{ __('Each product tab becomes real Products with an itemised bill of materials (material, ink, labour, overhead) reproducing the sheet\'s cost build-up, plus markup/buffer/risk pricing, quantity tiers, and the rate master (labour, overhead, ink). Optional tabs add the chart of accounts, asset register and startup capital.') }}

@elseif ($sourceType === 'bank')
{{-- Livewire stores uploads as random(30) . '-meta' . base64(name) . '-.ext', so the base64 expansion pushes a ~160-character original name past the 255-character limit a single filename has on most filesystems. That write happens before the component is reached, so no server-side rule can catch it, the upload would just spin. Hence the check here, before it starts. --}}
{{ __('Uploading…') }}

{{ __('That filename is too long to upload, Windows cannot store it. Rename the file to something short, like') }} statement.xlsx{{ __(', and choose it again.') }}

{{ __('A bank export (CSV or Excel, not PDF), the header block, running balance and fee lines are all read automatically. A cash book works too: any table with a date, a description and money-out / money-in columns, imported against the cash or wallet account it belongs to.') }}

{{ __('What each line becomes') }}

  • {{ __('Cash withdrawals and deposits → a transfer between this account and the cash account.') }}
  • {{ __('Ledger fees, transfer fees and transaction tax → an expense in Bank Charges, attached to the transaction that incurred it.') }}
  • {{ __('Receipts → a payment against the chosen invoice, or other income when none is chosen.') }}
  • {{ __('Payments out → an expense in the chosen category, optionally costed to a job.') }}
  • {{ __('Reversals → a treasury adjustment, which moves the balance without touching the P&L.') }}

{{ __('Lines matching an existing movement on this account are marked as duplicates and excluded. The resulting balance is verified against the statement\'s closing figure.') }}

@elseif ($sourceType === 'bundle')
{{ __('Uploading…') }}

{{ __('The .json file another workspace produced on its Data Export screen. Nothing is written until you have seen the preview.') }}

{{ __('What comes across, and what does not') }}

  • {{ __('Invoices and quotes with their lines, keeping the date they were raised.') }}
  • {{ __('Customers, products and categories are matched by name against this workspace, never created. A name that finds nothing is reported, and the document starts unticked.') }}
  • {{ __('Money is posted here rather than copied. An invoice arrives owing its full value, and the payments in the file are receipted again into accounts this workspace owns, matched by name like everything else.') }}
  • {{ __('The movement behind a payment or an expense is left out on purpose, because recording the payment raises it here. Only transfers and adjustments nothing else is behind travel as movements of their own.') }}
  • {{ __('A document number already in use here is renumbered, and the preview says so before anything is written.') }}

{{ __('Importing the same file twice changes nothing: every document remembers where it came from, and one already here is recognised rather than repeated.') }}

@else @if ($pdfUploads)

{{ __(':n file(s) ready.', ['n' => count($pdfUploads)]) }}

@endif @endif
@unless ($sourceType === 'products')
{{ __('Continue') }}
@endunless
@endif {{-- ======================= STEP 2: CONFIGURE (spreadsheet) ======================= --}} @if ($stage === 'configure')
@if (count($sheetNames) > 1)
@endif

{{ __('Pick the row that holds your column titles.') }}

{{-- Preview grid --}} @if ($previewGrid !== [])
@foreach (array_slice($previewGrid, 0, 8) as $i => $row) @foreach (array_slice($row, 0, 10) as $cell) @endforeach @endforeach
{{ $i + 1 }}{{ \Illuminate\Support\Str::limit($cell, 24) }}
@endif {{-- Column mapping --}}

{{ __('Map your columns') }}

{{ __('Only Item Name is required. Leave a field blank to skip it.') }}

@foreach ($this->fieldLabels() as $field => $label)
@endforeach
{{-- Grouping --}}

{{ __('Group rows into documents by') }}

{{ __('Start over') }} {{ __('Build preview') }}
@endif {{-- ======================= STEP 3: PREVIEW (P&L) ======================= --}} @if ($stage === 'preview' && $sourceType === 'pnl') @php $recon = $pnlSummary['reconciliation'] ?? ['parsed' => [], 'sheet' => [], 'months' => []]; $fmt = fn ($v) => number_format((float) $v, 2); @endphp

{{ __('Ready to import from :sheet', ['sheet' => $pnlSheet]) }}

@if ($pnlMode === 'sync') {{ __('Live sync, updates changed rows & removes deleted ones') }} @endif
@foreach ([ ['label' => __('Jobs'), 'value' => $pnlSummary['counts']['jobs'] ?? 0], ['label' => __('Operating-cost lines'), 'value' => $pnlSummary['counts']['opex'] ?? 0], ['label' => __('Customers'), 'value' => $pnlSummary['counts']['customers'] ?? 0], ] as $stat)

{{ $stat['value'] }}

{{ $stat['label'] }}

@endforeach
{{-- Reconciliation: parsed vs the sheet's own month-summary rows --}}

{{ __('Reconciliation (parsed vs sheet totals)') }}

{{ __('Revenue') }} {{ __('Production cost') }} {{ __('Operating cost') }}
{{ __('Parsed') }} {{ $fmt($recon['parsed']['revenue'] ?? 0) }} {{ $fmt($recon['parsed']['cost'] ?? 0) }} {{ $fmt($recon['parsed']['opex'] ?? 0) }}
{{ __('Sheet totals') }} {{ $fmt($recon['sheet']['revenue'] ?? 0) }} {{ $fmt($recon['sheet']['cost'] ?? 0) }} {{ $fmt($recon['sheet']['opex'] ?? 0) }}
@if (! empty($pnlSummary['warnings']))
@foreach ($pnlSummary['warnings'] as $w)

⚠ {{ $w }}

@endforeach
@endif
{{-- Sample of the jobs that will be created --}} @if (! empty($pnlSummary['sample_jobs']))
{{ __('First :n jobs', ['n' => count($pnlSummary['sample_jobs'])]) }}
@foreach ($pnlSummary['sample_jobs'] as $j) @endforeach
{{ __('Month') }} {{ __('Job') }} {{ __('Customer') }} {{ __('Revenue') }} {{ __('Cost') }}
{{ $j['month'] }} {{ \Illuminate\Support\Str::limit($j['title'], 48) }} @if ($j['reprints'] > 0){{ __(':n reprint(s)', ['n' => $j['reprints']]) }}@endif {{ \Illuminate\Support\Str::limit($j['customer'], 28) }} {{ $fmt($j['revenue']) }} {{ $fmt($j['cost']) }}
@endif
{{ __('Start over') }} {{ __('Import now') }} {{ __('Importing…') }}
@endif {{-- ======================= STEP 3: PREVIEW ======================= --}} {{-- ======================= STEP 3: PREVIEW (bank statement) ======================= --}} @if ($stage === 'preview' && $sourceType === 'bank' && $bankStatement) @php $statement = $this->statement(); $bankRows = $statement->principalRows(); $recon = $this->bankReconciliation(); $kinds = \App\Services\Import\Data\BankStatementRow::KINDS; $accountKinds = ['cash_withdrawal', 'cash_deposit', 'transfer', 'personal']; $expenseKinds = ['payment_out', 'bank_charge']; @endphp

{{ $statement->bank ?: __('Bank statement') }}

{{ $statement->accountName }} @if ($statement->accountNumber) · {{ $statement->accountNumber }} @endif @if ($statement->currency) · {{ $statement->currency }} @endif

@if ($statement->periodFrom && $statement->periodTo)

{{ $statement->periodFrom->format('d M Y') }} → {{ $statement->periodTo->format('d M Y') }}

@endif
{{-- The parse is only trustworthy if the bank's own closing figure is reproduced. --}}
$recon['checkable'] && $recon['matches'], 'border-rose-200 bg-rose-50' => $recon['checkable'] && ! $recon['matches'], 'border-slate-200 bg-slate-50' => ! $recon['checkable'], ])>
$recon['checkable'] && $recon['matches'], 'text-rose-600' => $recon['checkable'] && ! $recon['matches'], 'text-slate-400' => ! $recon['checkable'], ]) /> @if (! $recon['checkable']) {{ __('No closing balance to check') }} @elseif ($recon['matches']) {{ __('Statement reads clean') }} @else {{ __('Statement does not balance') }} @endif

{{ __('Opening :o + movements = :d', ['o' => number_format($statement->openingBalance ?? 0, 2), 'd' => number_format($recon['expected'], 2)]) }} @if ($recon['closing'] !== null) · {{ __('bank says :c', ['c' => number_format($recon['closing'], 2)]) }} @endif

{{ __('Transactions') }}

{{ count($bankRows) }}

{{ __('Fee lines folded in') }}

{{ count($statement->rows) - count($bankRows) }}

{{ __('Money in') }}

{{ number_format($statement->totalIn(), 2) }}

{{ __('Money out') }}

{{ number_format($statement->totalOut(), 2) }}

@if ($bankDuplicates !== [])

{{ __(':n row(s) look already recorded', ['n' => count($bankDuplicates)]) }}

{{ __('These match a movement already on this account by amount, direction and date. They start unticked so nothing is counted twice, tick one back on only if you are sure it is a separate transaction.') }}

@endif
@foreach ($bankRows as $row) @php $i = $row->index; $kind = $bankDecisions[$i]['kind'] ?? $row->kind; $fees = $statement->totalFeesFor($i); $isDupe = isset($bankDuplicates[$i]); @endphp $isDupe])> @endforeach
{{ __('Use') }} {{ __('Date') }} {{ __('Description') }} {{ __('Amount') }} {{ __('Fees') }} {{ __('Treat as') }} {{ __('Post to') }}
{{ $row->date?->format('d M Y') }}

{{ \Illuminate\Support\Str::limit($row->description, 90) }}

@if ($isDupe) {{ __('Possibly already recorded') }} @endif
$row->direction() === 'in', 'text-rose-700' => $row->direction() === 'out', ])> {{ $row->direction() === 'in' ? '+' : '−' }}{{ number_format($row->amount(), 2) }} {{ $fees > 0 ? number_format($fees, 2) : '—' }} @if (in_array($kind, $accountKinds, true)) @elseif (in_array($kind, $expenseKinds, true)) @elseif ($kind === 'receipt') @else — @endif
{{ __('Start over') }} {{ __('Import these rows') }} {{ __('Importing…') }}
@endif {{-- ======================= STEP 4: DONE (bank statement) ======================= --}} @if ($stage === 'done' && $sourceType === 'bank' && $bankResult)

{{ __('Statement imported') }}

{{ __(':created created · :duplicates already present · :skipped skipped', [ 'created' => $bankResult['created'], 'duplicates' => $bankResult['duplicates'], 'skipped' => $bankResult['skipped'], ]) }}

@if ($bankResult['by_kind'] !== [])
@foreach ($bankResult['by_kind'] as $kind => $count) {{ \App\Services\Import\Data\BankStatementRow::KINDS[$kind] ?? $kind }}: {{ $count }} @endforeach
@endif @if ($bankResult['errors'] !== [])

{{ __('Rows that could not be imported') }}

    @foreach ($bankResult['errors'] as $error)
  • {{ $error }}
  • @endforeach

{{ __('Fix the cause, then re-import the same file, rows already in are recognised and left alone.') }}

@endif @if ($this->bankAccount())

{{ __(':name now reads :balance.', [ 'name' => $this->bankAccount()->name, 'balance' => number_format($this->bankAccount()->fresh()->balance, 2), ]) }} {{ __('Compare that against the closing balance printed on the statement, if they agree, the account is fully reconciled.') }}

@endif
{{ __('Import another') }} {{ __('Open Treasury') }}
@endif {{-- ============ TRANSACTION BUNDLE: PREVIEW ============ --}} @if ($stage === 'preview' && $sourceType === 'bundle' && $bundlePlan) @php // Named and iconed by the import plan, which got them from the // registry, so a new kind of record gets a section by arriving. $entityMeta = $bundlePlan['entities'] ?? []; $stateMeta = [ 'new' => ['label' => __('New here'), 'color' => 'emerald'], 'renumbered' => ['label' => __('Renumbered'), 'color' => 'amber'], 'adopted' => ['label' => __('Already here'), 'color' => 'slate'], ]; @endphp

{{ $bundlePlan['workspace'] }} {{ __('wrote this file, covering :from to :to.', [ 'from' => \Illuminate\Support\Carbon::parse($bundlePlan['window']['from'])->format('j M Y'), 'to' => \Illuminate\Support\Carbon::parse($bundlePlan['window']['to'])->format('j M Y'), ]) }} @if ($bundlePlan['manifest']['generated_by'] ?? null) {{ __('Exported by :who.', ['who' => $bundlePlan['manifest']['generated_by']]) }} @endif

{{ __('Nothing has been written yet.') }} {{ __('Untick anything that should stay out, then import. Documents already here are recognised and left alone whatever you tick.') }}

@foreach ($bundlePlan['warnings'] as $warning)

{{ $warning }}

@endforeach
@foreach ($bundlePlan['rows'] as $entity => $rows) @continue ($rows === [])

{{ $entityMeta[$entity]['label'] }}

{{ __(':new new · :renumbered renumbered · :adopted already here · :lines line(s)', [ 'new' => $bundlePlan['totals'][$entity]['new'], 'renumbered' => $bundlePlan['totals'][$entity]['renumbered'], 'adopted' => $bundlePlan['totals'][$entity]['adopted'], 'lines' => $bundlePlan['totals'][$entity]['lines'], ]) }}

@foreach ($rows as $row) @endforeach
{{ __('Number') }} {{ __('Raised') }} {{ __('Customer') }} {{ __('Lines') }} {{ __('Total') }} {{ __('What happens') }}
{{ $row['final_number'] }} @if ($row['final_number'] !== $row['number']) {{ __('was :number', ['number' => $row['number']]) }} @endif {{ $row['issued_at'] ? \Illuminate\Support\Carbon::parse($row['issued_at'])->format('j M Y') : '—' }} @if ($row['customer_id']) {{ $row['customer'] }} @else {{ $row['customer'] ?? __('nobody') }} @endif {{ $row['lines'] }} {{ $row['currency_code'] }} {{ number_format($row['total'], 2) }} {{ $stateMeta[$row['state']]['label'] }} @if ($row['issues'] !== [])
    @foreach ($row['issues'] as $issue)
  • {{ $issue }}
  • @endforeach
@endif
@endforeach
{{ __('Choose another file') }} {{ __('Import the ticked documents') }} {{ __('Importing…') }}
@endif {{-- ============ TRANSACTION BUNDLE: DONE ============ --}} @if ($stage === 'done' && $sourceType === 'bundle' && $bundleResult)

{{ __('Bundle imported') }}

{{ __(':imported imported · :adopted already here · :skipped left out · :lines line(s)', [ 'imported' => array_sum($bundleResult['imported']), 'adopted' => array_sum($bundleResult['adopted']), 'skipped' => array_sum($bundleResult['skipped']), 'lines' => $bundleResult['lines'], ]) }}

{{ __('Every invoice came in owing its full value, and only the payments in the file will have settled it. Anything still showing a balance is either genuinely unpaid or was paid by something that did not travel: receipt those here as the customer pays, so the cash and the ledger agree.') }}
@if ($bundleResult['warnings'] !== [])

{{ __('Worth knowing') }}

    @foreach ($bundleResult['warnings'] as $warning)
  • {{ $warning }}
  • @endforeach

{{ __('Fix the cause, then import the same file again, everything already in is recognised and left alone.') }}

@endif
{{ __('Import another') }} {{ __('Open Invoices') }}
@endif @if ($stage === 'preview' && ! in_array($sourceType, ['pnl', 'bank', 'bundle'], true)) @php $meta = $this->meta; @endphp @if ($parseErrors !== [])

{{ __('Some PDFs were skipped:') }}

    @foreach ($parseErrors as $err)
  • {{ $err }}
  • @endforeach
@endif {{-- Import options --}}

{{ __('Import options') }}

{{-- Sync mode --}}
@if ($syncMode)

{{ __('Sync handles existing records automatically.') }}

@else @endif
@if ($recordPayments)

{{ __('Only PAID invoices in the account currency are recorded.') }}

@endif
@if ($documents === []) {{ __('Start over') }} @else

{{ __(':n document(s) ready', ['n' => count($documents)]) }}

·
@foreach ($documents as $i => $doc) @php $m = $meta[$i] ?? ['customer_exists' => false, 'products' => [], 'valid' => true]; @endphp
{{ $doc['customer_name'] }} @if ($m['customer_exists']) {{ __('existing customer') }} @else {{ __('new customer') }} @endif {{ $doc['status'] }}

{{ $doc['document_number'] ?: __('(number will be generated)') }} @if ($doc['date']) · {{ $doc['date'] }} @endif @if ($doc['currency_code']) · {{ $doc['currency_code'] }} @endif

{{ __('Total') }}

{{ number_format($doc['totals']['total'] ?? 0, 2) }}

@if (($doc['cost_total'] ?? null) !== null) @php $docTotal = $doc['totals']['total'] ?? 0; $docMargin = $docTotal > 0 ? round((($docTotal - $doc['cost_total']) / $docTotal) * 100) : null; @endphp

{{ __('Cost') }} {{ number_format($doc['cost_total'], 2) }}@if ($docMargin !== null) · {{ $docMargin }}%@endif

@endif
@foreach ($doc['lines'] as $line) @endforeach
{{ __('Item') }} {{ __('Qty') }} {{ __('Rate') }} {{ __('Discount') }} {{ __('Total') }}
{{ $line['name'] }} @if (! ($m['products'][$line['name']] ?? false)) {{ __('new') }} @endif
@if (! empty($line['description']))

{{ \Illuminate\Support\Str::limit($line['description'], 90) }}

@endif
{{ rtrim(rtrim(number_format($line['qty'], 2), '0'), '.') }} {{ number_format($line['unit_price'], 2) }} {{ number_format($line['discount'], 2) }} {{ number_format($line['line_total'], 2) }}
@if (! empty($doc['warnings']))
@foreach ($doc['warnings'] as $w)

⚠ {{ $w }}

@endforeach
@endif
@endforeach
{{ __('Back') }} {{ __('Import now') }} {{ __('Importing…') }}
@endif @endif {{-- ======================= STEP 4: DONE (P&L) ======================= --}} @if ($stage === 'done' && $sourceType === 'pnl' && $pnlResult) @php $c = $pnlResult['counts']; @endphp

{{ __('P&L imported') }}

{{ __('Your monthly jobs and operating costs are now in BillPro.') }}

@php $pnlStats = $pnlMode === 'sync' ? [ ['label' => __('New jobs'), 'value' => $c['jobs'] ?? 0], ['label' => __('Updated'), 'value' => ($c['jobs_updated'] ?? 0) + ($c['expenses_updated'] ?? 0)], ['label' => __('Unchanged'), 'value' => $c['unchanged'] ?? 0], ['label' => __('Removed'), 'value' => $c['pruned'] ?? 0], ['label' => __('Customers'), 'value' => $c['customers'] ?? 0], ['label' => __('Expenses'), 'value' => $c['expenses'] ?? 0], ['label' => __('Funding'), 'value' => $c['job_funding'] ?? 0], ['label' => __('Director loans'), 'value' => $c['director_loans'] ?? 0], ] : [ ['label' => __('Jobs'), 'value' => $c['jobs'] ?? 0], ['label' => __('Invoices'), 'value' => $c['invoices'] ?? 0], ['label' => __('Job costs'), 'value' => $c['job_costs'] ?? 0], ['label' => __('Customers'), 'value' => $c['customers'] ?? 0], ['label' => __('Expenses'), 'value' => $c['expenses'] ?? 0], ['label' => __('Funding'), 'value' => $c['job_funding'] ?? 0], ['label' => __('Director loans'), 'value' => $c['director_loans'] ?? 0], ['label' => __('Skipped'), 'value' => $c['skipped'] ?? 0], ]; @endphp
@foreach ($pnlStats as $stat)

{{ $stat['value'] }}

{{ $stat['label'] }}

@endforeach
@if (! empty($pnlResult['notes']))

{{ __('Notes') }}

@foreach ($pnlResult['notes'] as $n)

⚠ {{ $n }}

@endforeach
@endif @if (! empty($pnlResult['errors']))

{{ __(':n row(s) could not be imported', ['n' => count($pnlResult['errors'])]) }}

@foreach (array_slice($pnlResult['errors'], 0, 20) as $e)

{{ $e }}

@endforeach
@endif
{{ __('Import another') }} {{ __('View jobs') }}
@endif {{-- ======================= STEP 4: DONE (products & costs) ======================= --}} @if ($stage === 'done' && $sourceType === 'products' && $productsResult) @php $c = $productsResult['counts'] ?? []; @endphp

{{ __('Products & costs imported') }}

{{ __('Your costing workbook is now in BillPro.') }}

@foreach ([ ['label' => __('Products'), 'value' => $c['products'] ?? 0], ['label' => __('BOM lines'), 'value' => $c['bom_lines'] ?? 0], ['label' => __('Price tiers'), 'value' => $c['tiers'] ?? 0], ['label' => __('Operating costs'), 'value' => $c['operating_costs'] ?? 0], ['label' => __('Ink modes'), 'value' => $c['ink_modes'] ?? 0], ['label' => __('Accounts'), 'value' => $c['accounts'] ?? 0], ['label' => __('Assets'), 'value' => $c['assets'] ?? 0], ['label' => __('Capital'), 'value' => $c['capital'] ?? 0], ['label' => __('Director loans'), 'value' => $c['director_loans'] ?? 0], ['label' => __('Prices updated'), 'value' => $c['prices_updated'] ?? 0], ['label' => __('Currencies'), 'value' => $c['currencies'] ?? 0], ] as $stat)

{{ $stat['value'] }}

{{ $stat['label'] }}

@endforeach
@if (! empty($productsResult['notes']))

{{ __('Notes') }}

@foreach ($productsResult['notes'] as $n)

⚠ {{ $n }}

@endforeach
@endif
{{ __('Import another') }} {{ __('View products') }}
@endif {{-- ======================= STEP 4: DONE ======================= --}} @if ($stage === 'done' && ! in_array($sourceType, ['pnl', 'products', 'bank', 'bundle'], true) && $result)

{{ __('Import complete') }}

{{ __('Your past jobs are now in BillPro.') }}

@foreach (array_filter([ ['label' => __('New invoices'), 'value' => $result['invoices_created'], 'color' => 'indigo'], $syncMode ? ['label' => __('Updated'), 'value' => $result['invoices_updated'] ?? 0, 'color' => 'sky'] : null, $syncMode ? ['label' => __('Unchanged'), 'value' => $result['invoices_unchanged'] ?? 0, 'color' => 'slate'] : null, $syncMode ? ['label' => __('Removed'), 'value' => $result['records_pruned'] ?? 0, 'color' => 'rose'] : null, ['label' => __('Jobs'), 'value' => $result['jobs_created'], 'color' => 'violet'], ['label' => __('Job costs'), 'value' => $result['job_costs_created'] ?? 0, 'color' => 'amber'], ['label' => __('Customers'), 'value' => $result['customers_created'], 'color' => 'emerald'], ['label' => __('Products'), 'value' => $result['products_created'], 'color' => 'sky'], ['label' => __('Payments'), 'value' => $result['payments_created'], 'color' => 'amber'], ! $syncMode ? ['label' => __('Skipped'), 'value' => $result['documents_skipped'], 'color' => 'slate'] : null, ]) as $stat)

{{ $stat['value'] }}

{{ $stat['label'] }}

@endforeach
@if (! empty($result['skipped']))

{{ __('Skipped') }}

@foreach ($result['skipped'] as $s)

{{ $s['ref'] }}, {{ $s['message'] }}

@endforeach
@endif @if (! empty($result['errors']))

{{ __('Errors') }}

@foreach ($result['errors'] as $e)

{{ $e['ref'] }}, {{ $e['message'] }}

@endforeach
@endif
{{ __('Import another') }} {{ __('View jobs') }}
@endif