Skip to Content
FeaturesCRM (Beta)Overview

CRM (Beta)

Beta — use at your own risk. The CRM module is feature-flagged off by default on every install. The schema is settled, the workflows have been tested end-to-end, but the surface is broad and new — expect edge cases, polish gaps, and missing translations outside EN + DE. Seeded contract blocks, payment-term templates, and tax defaults are examples only; verify with a lawyer, your bank, and your tax advisor before sending any real document to a customer.

PicPeak ships an integrated CRM module that lives alongside the gallery side of the product: quotes → contracts → invoices end-to-end, hour logging, a unified calendar, and a tax report. Every document in one engagement shares a deal_uuid so the lineage card on each detail page shows you the full chain at a glance.

Customers are shared by every admin on one install, but quotes, contracts and invoices belong to the admin who created them: other admins do not see them, and a super admin sees everything. See Tenancy model below.

The CRM is the sales-side module — quotes, contracts, invoices issued to customers. The cost-side counterpart (supplier invoice capture, internal expenses, Treuhänder export) is the separate Accounting module. They share the same data model but the surfaces split: /admin/clients/* for CRM, /admin/accounting/* for accounting.

Modules

ModuleWhat it doesDocs
Customer groupsSort customers into groups, filter the customer list by them, change them in bulk, and target newsletters and workflows at them. Beta channel only.Customer groups
QuotesCreate, send, accept/decline, convert to event + contract + invoice. Public response page for the customer.Quotes
ContractsBlock-based composition, in-browser signing, countersign, integrity check on stored PDF. Several signers and the signing lifecycle are beta channel only.Contracts
InvoicesSingle-row and installment-spawned invoices, Storno (cancellation) for §14 / §11 UStG compliance, monthly drafts, payment-check token on the customer side.Invoices
Hours loggingPer-customer hourly rate, log entries against a customer, bill them into an invoice with one click.Hours logging
CalendarDrag-create hour entries, calendar view of events + entries.Calendar
Tax reportPer-period summary export for your tax return. Lives under the Accounting module since PR #622.Tax report
Customer portal (CRM surfaces)What customers see on their portal: quotes to respond to, contracts to sign, invoices to pay.Customer portal CRM views

CRM admin settings live under Settings → CRM (see Admin Settings → CRM); accounting-side settings (chart of accounts, VAT codes, VAT registration, default rates) live under Settings → Accounting (see Admin Settings → Accounting).

Turning the CRM on

The CRM ships completely off on every install. To enable:

  1. Open Settings → Features.
  2. Enable each CRM sub-feature you want to use. There is no separate master switch: the CRM sidebar section (the /admin/clients/* surface) appears as soon as one of them, or Customer Accounts, is on, and disappears when all are off. Quotes, Contracts, Invoices and Hours logging are in the Sales section of the Features tab, Calendar under Scheduling:
    • Quotes — quote editor + public response page
    • Invoices (bills) — invoice editor + Storno + customer-side bills tab
    • Contracts — block library + send + signing flow
    • Hours logging — per-customer hour entries + “Bill these hours” flow
    • Calendar — calendar view of events and hour entries
  3. Optional: enable CRM developer tools (under Insights & Access) to access the in-app email-template tester (/admin/clients/dev). Strictly opt-in; useful when you want to preview a quote_sent or invoice_paid_receipt email without waiting for the real lifecycle event.

If you want the cost-side tracking (supplier invoices, expenses) and the Treuhänder export, also enable the Accounting module — see the Accounting overview. The Tax report sub-flag (taxReport) lives there now, not under CRM.

Dependency rules enforced server-side:

  • quotes=false forces bills=false (an invoice without a quote chain is still allowed, but the bills UI hides if quotes are off, and most paths assume both are present).
  • calendar=false forces calendarBooking=false (the latter is a roadmap placeholder — see below).

Locked roadmap flags

Three flags appear in the Features tab as placeholders with a lock icon:

  • reminderEmails (parent flag — individual reminder template settings still apply when this is locked)
  • calendarBooking (customer self-booking against the admin calendar)
  • messaging (admin ↔ customer thread on the portal)

These are intentional UI surfaces for features that are designed but not yet built. Enabling them in the Features tab has no effect — the server side clamps them to false on every save. They live there so you can see what’s on the roadmap without a separate planning page.

Tenancy model

Quotes, contracts and invoices belong to the admin who created them. On stable from v3.134.2 and on beta from v3.167.3-beta.0 (PicPeak PR #1884 ) an admin sees and edits only the documents they created (created_by_admin_id), together with everything that hangs off them: line items, payments, PDFs, signers, history. A super admin sees every document. The *.view / *.manage permissions still decide whether an admin can work with a document class at all; the owner rule narrows that to their own documents.

  • Another admin’s document answers as if it did not exist (404), on every read and write route, before any upload or other side effect.
  • Ownership cannot be handed over. A document’s creator is fixed when it is created.
  • Older documents without a creator are reachable by the admin who created the gallery or project they are linked to, or who created another document in the same deal. A deal that holds a document created by a different admin is not reachable this way by anyone but a super admin.
  • Linking a gallery to an invoice needs the gallery’s creator or a super admin — see Invoices → Changing the customer or the gallery.
  • The tax report and the journal export cover every invoice of the studio, so only a super admin can produce them. Anyone else gets “This report covers every invoice of the studio. Your account only sees its own documents, so the report is not available to you.” (403 CRM_COMPLETE_VIEW_REQUIRED).
  • The calendar shows the quotes and contracts the admin can see.
  • Customer documents (beta channel only) attached to a contract follow the contract.
  • Customers and hour entries stay shared. Every admin with the customer permissions sees every customer.
  • Workflows reach only the documents of the admin whose action started them; editing a workflow grants no access to anyone else’s documents. The built-in scheduled jobs (scheduled sends, reminders, dunning) keep working on every document.

Internal expenses and incoming invoices in the Accounting module follow a similar rule.

Behaviour change on upgrade. Earlier builds let every admin with a CRM permission see every quote, contract and invoice. A studio that used the built-in admin role to run the books for everyone needs a super admin for that view after the upgrade.

Every action is still recorded in the activity_log table (send, convert, countersign, …), so the audit trail names who did what.

PicPeak ships with example data for several legally and financially sensitive areas. These are starting points for you to customise — none of them is legal or financial advice.

Contract blocks

The block library is seeded with example clauses for common photo-shoot contract structures (booking fee, deliverables, copyright, cancellation, etc.). They are written in plain German and English as templates, not as enforceable text reviewed for any specific jurisdiction.

Before you ever send a contract to a customer, have a lawyer in your jurisdiction review the blocks you intend to use. The editor surfaces a disclaimer reminder near the Send action — see Contracts for the full disclosure path.

Payment terms

Seeded payment-term templates (“Net 14”, “Net 30”, “Sofort fällig”, “10% Anzahlung / 90% nach Lieferung”, etc.) are presets — they assume defaults like 14-day Skonto windows that may not match your actual terms. Audit and edit them in Settings → CRM → Payment terms before using.

IBAN, QR-bill, and tax settings

business_profile carries your IBAN, your bank reference details, and your default tax rate. The seeded values are placeholders that get filled in from your installation env / first-run. Confirm with your bank that the IBAN + reference format you ship to customers is what their systems expect, especially if you’re issuing Swiss QR-bills (the swissqrbill library is used to render them — formatting choices like creditor reference type can vary by bank).

Tax export

The tax-report export aggregates invoice totals by period. It is a summary for your accountant, not a tax filing. The categorisation, VAT-rate inheritance, and Storno netting rules are documented per Tax report, but your accountant is the source of truth for what your jurisdiction requires.

See docs/crm-disclaimers.md in the main repo for the full disclaimer set the project commits to.

Customer portal CRM views

When customer accounts are enabled (clients + customerPortal feature flags), customers logging in at /customer/login see additional tabs alongside their gallery dashboard:

  • Quotes — pending quotes waiting on their response, accepted/declined history.
  • Contracts — contracts to sign, signed contracts to download.
  • Bills — open invoices with payment instructions (IBAN, QR-bill PDF download), paid history with receipts.

Each customer’s CRM tabs are gated by the customer_accounts.feature_quotes / feature_bills / feature_contracts toggles on that customer’s profile — so you can selectively expose them per-customer (a wedding client probably doesn’t need the contracts tab post-shoot; a commercial client might want the full set).

See Customer accounts for the underlying authentication and assignment model.

Storage requirements

The CRM stores generated PDFs (quotes, contracts, invoices, Storno documents) on the storage backend you’ve configured for galleries (local disk, S3, or external-media path). One PDF per document, plus the customer-signed PDF for contracts. Sizing is modest — expect ~50–200 KB per document.

PDFs are regenerated on each send (so cosmetic changes to your business profile flow into the next send automatically), but the stored PDF is what was actually delivered. The integrity check on contracts uses a SHA-256 of the stored bytes — see Contracts.

Database notes

The CRM adds approximately 20 new tables in migration 107_crm_consolidated.js, all idempotent (hasTable/hasColumn guarded). Fresh installs see no impact when the feature flags are off — empty tables, no traffic, no admin UI surfaces.

Money is stored as INTEGER minor units (cents/Rappen) + ISO 4217 currency code — never DECIMAL/FLOAT, to avoid drift on totals.

deal_uuid (the lineage key) is a UUID assigned to the first document in a chain (usually a quote) and carried forward to every document spawned from it. The lineage card on each detail page joins on it to show you “this quote → that contract → those installment invoices” in one view.

Known limitations

Single-day events only on the calendar. Multi-day, recurring events, iCal/.ics export, and overlap conflict warnings are deliberate scope deferrals — see the project backlog. Customer self-booking against the calendar is in the roadmap but not yet built (the calendarBooking flag is locked).

createQuote and the equivalent invoice / contract create paths use the claimNextSequence helper for gap-free numbering. On SQLite this requires the in-transaction handoff that landed in d1aecaa  — if you’re running an older snapshot, upgrade or formally require PostgreSQL.

Last updated on