Skip to content
LeitaguDocs

Loading…

Pages

Platform

Internal CRM

The Leitagu team's research CRM for Estonian furniture companies that could become partners: access, data, statuses and scales, the pipeline, importing research data, and turning a company into a partner store.

Updated 16 October 2026View as Markdown

The research CRM (kliendiuuring) at crm.leitagu.ee is the Leitagu team's tool for finding and working with Estonian furniture makers and sellers that could become partners. Every company is a lead: what we know about it, where each fact came from, who we talk to there, and where it is in the pipeline. It ships with a research dataset of 99 companies and 10 organisations, collected from search results, which must be checked before anyone is contacted. When a company signs up, one button creates its store for the partner app.

Who can use it

  • Admins only. Only accounts with the admin role can log in: those listed in ADMIN_EMAILS, or promoted with npm run make-admin. Shop and store accounts are refused.
  • Its own login. The CRM has its own session cookie (leitagu_crm), which lasts 12 hours. A shop or admin session doesn't open it.
  • Checks everywhere. Every page and API route checks the admin role itself.
  • Audit log. Importing data, deleting a company and making a company a partner are written to the audit log, which the admin app shows.

What is in it

Page Estonian What it shows
Overview Ülevaade Companies per status; high-priority companies nobody has contacted yet; your own open companies; recently changed companies; data gaps; open tasks
Companies Ettevõtted A searchable, filterable list with CSV export, and a profile page per company
Pipeline Müügitoru A board with one column per status
Tasks Ülesanded Open tasks from every company, grouped as overdue, today and upcoming
Organisations Organisatsioonid Industry bodies and other organisations found during research
Import Impordi Loads a research dataset (JSON)

On the overview, "high priority, not contacted yet" means priority high and status new, researching or qualified, best fit first. Data gaps count companies without a registry code, without a website, and with unverified data, leaving out those marked not a fit or lost.

Company list

  • Search (Otsi) looks in the name and legal name, and matches the registry code, a tag, a location or a brand exactly. The head office city is matched without case.
  • Filters: status (including "all open"), type, priority, data confidence and owner (including "nobody").
  • Order: priority and fit (the default: high priority first, then highest fit, then name), name, last change, or revenue.
  • Limit: a list shows at most 1,000 companies.

Company profile

  • Overview: description, why the company matters to Leitagu, history and research notes.
  • Facts: legal name, registry code (linked to the Estonian Business Register), website, webshop and its platform, head office and stores, founding year, employees and revenue with their year, parent company, brands, export focus, types and segments.
  • Tracking: owner, last contact and data confidence.
  • Status, priority, fit and next step, with an optional due date for the next step.
  • Activity, contacts, news and sources (see below).

Data model

The tables come from migration 004_crm.mjs.

Table Holds
crm_companies One row per company (lead): its facts, Leitagu's assessment (relevance, fit, priority, status, owner, tags, data confidence, research notes, next step and due date, last contact), whether it was added by hand or imported, and store_id, the link to its store once it is a partner
crm_contacts People at a company: name, role, email, phone, LinkedIn and notes
crm_activities The timeline: notes, calls, emails, meetings, tasks (with due and done times) and automatic status changes
crm_news News about a company: title, link, date, source and summary
crm_sources The pages research facts came from: address, title, when accessed, and which fields the page supports
crm_organisations Industry bodies and similar organisations, with their sources

Each company has a unique slug, used to match imports. Deleting a company also deletes its contacts, activities, news and sources; a store already made from it stays.

Statuses

The pipeline has eight statuses. The first five are open; the last three close the lead.

Status Estonian Meaning What the CRM does
New Uus Added and not worked on yet Companies added by hand start here, and so do imported ones unless the file gives another status
Researching Uurimisel Someone is checking the facts —
Qualified Sobiv Checked, and worth approaching —
Contacted Ühendust võetud We have reached out Sets "last contact" to now
In talks Läbirääkimised A conversation about joining is under way Sets "last contact" to now
Partner Partner The company has joined Leitagu Set by "Make a partner"
Not a fit Ei sobi Not suitable for Leitagu Left out of data-gap counts
Lost Kaotatud Was a prospect, but it didn't work out Left out of data-gap counts

Every status change is added to the company's activity feed automatically, with the old and new status. These entries can't be deleted.

Priority, fit and confidence

Priority (Prioriteet) is high (Kõrge), medium (Keskmine) or low (Madal), and medium by default. In the research dataset it is the suggested order of outreach, combining fit with the company's size and how easy integration looks.

Fit (Sobivus) is 1–5: how well the company matches Leitagu as a source of products shoppers can buy. The scale, from the research dataset's definitions:

Fit Meaning
5 Sells to Estonian consumers and has a confirmed webshop (an ideal early partner)
4 Consumer-facing, but the webshop is unconfirmed, or the company is hard to partner with (IKEA franchise, marketplaces, stock held abroad)
3 Consumer-facing but niche (kitchens, second-hand, single brand), or a maker that sells some products to consumers
2 Mostly B2B, contract or export, with only indirect consumer reach
1 Export-only, components, or not really furniture-focused

Data confidence (Andmete usaldusväärsus):

Value Estonian Meaning
Verified Kontrollitud The key facts (identity, registry code, type, plus figures or locations) are each backed by a source
Partly verified Osaliselt kontrollitud Identity and some facts are backed, but key items such as the registry code or financials are missing
Unverified Kontrollimata Only that the company exists or existed, or the sources are thin or old

Types are retailer, webshop (online retailer), marketplace, maker, kitchen maker, designer-maker, importer or wholesaler, second-hand, and contract supplier. A company can have several. Segments are the product areas it covers, such as living room, bedroom, solid wood or mattresses.

Activity and tasks

Kind Estonian Notes
Note Märkus Free text
Call Kõne Sets the company's "last contact" to now
Email E-kiri Sets "last contact" to now
Meeting Kohtumine Sets "last contact" to now
Task Ülesanne Has an optional due date (stored as 09:00 Estonian time that day); can be marked done (Tehtud) and reopened
Status change Staatuse muutus Added automatically; can't be deleted
  • Tasks page. Open tasks from all companies, grouped as overdue (Hilinenud), today (Täna) and upcoming (Tulemas), each with a done button.
  • Deleting. Notes, calls, emails, meetings and tasks can be deleted; status changes stay as history.
  • Next step. Separate from tasks, each company has one "next step" text with an optional due date, shown on its pipeline card and used to order "my companies" on the overview.

Pipeline board

The pipeline (Müügitoru) has one column per status, all eight of them. Each card shows the company's name, priority, fit, city, owner, next step and its due date.

  • Drag a card to another column to change its status.
  • Or use the status menu on the card, which also works from the keyboard.

Either way the change is logged in the company's activity feed.

Importing research data

Import (Impordi) takes a JSON file with a companies list and an optional organisations list, in the format of data/research/schema.json. The button "Import the research dataset in the repository" loads the bundled file without uploading anything. An uploaded file can be up to 20 MB.

  • Matching. A company's id becomes its slug, and a company already in the CRM with the same slug is updated rather than duplicated.
  • New companies get all their facts, sources and news, and a note in the activity feed saying they came from the import. Their status is taken from the file if it is valid, otherwise new.
  • Existing companies: only fields that are empty in the CRM are filled, and new sources and news are added. Priority and status are never changed. Anything the team has edited stays as it is, so the same file can be imported again safely.
  • News without a link is matched by its title, so it isn't added twice.
  • Organisations are matched by id and replaced with the file's version. They can't be edited in the CRM.
  • Invalid records are skipped and listed after the import. Unknown types and segments are dropped, unknown statuses become new, and a fit outside 1–5 is left empty.
  • The result reports how many companies were added, filled in or left unchanged, and how many organisations were loaded.

The bundled dataset

data/research/estonian-furniture-companies.json holds 99 companies and 10 organisations (associations and public bodies), compiled on 16 October 2026. It is built into the CRM's server, so it can be imported on any host.

  • Coverage. By confidence: 39 verified, 46 partly verified, 14 unverified. By priority: 18 high, 34 medium, 47 low. By fit: 14 at 5, 13 at 4, 34 at 3, 26 at 2 and 12 at 1. 68 have a registry code, 34 a website and 28 a confirmed webshop. All start with the status new and no contact people.

Caveats, from the dataset's README:

  • It is a research draft, not a verified contact list. Every record needs a human check in the Business Register (äriregister) before anyone contacts the company.
  • Search results only. About 200 web searches in Estonian and English. Pages were not opened, so every fact comes from search-result titles, addresses and summaries.
  • One rule: a field has a value only if a search result supported it, and that source is listed with the fields it supports. Everything else is empty, and the gaps are explained in the research notes.
  • Known weaknesses. Registry aggregators sometimes show forecasts or mislabel years. Some sources are written by the companies themselves. A website is recorded only when a result showed it. An empty webshop field means "not confirmed", not "no".
  • Incomplete. The search budget ran out at 99 companies, short of the target of 120. Small shops, kitchen makers and regional workshops are under-covered.

To change the dataset: edit the JSON, run npm run research:validate, commit, deploy the CRM, and press the import button again. Existing edits in the CRM are kept.

Make a partner

When a company signs up, "Make a partner" (Tee partneriks) on its profile:

  1. links the store that already exists under the company's name (by address or name, for example one from the example data), as long as no other company is linked to it; otherwise it creates a store for the partner app, named after the company and with its website;
  2. links the company to the store (crm_companies.store_id);
  3. sets the status to partner, which is logged in the activity feed;
  4. writes the conversion to the audit log.

The profile then shows the partner store, with a link to it in the admin app. The store's first invite link is created there (admin app → Stores), and the team sends it on; see Getting access.

Pressing the button again for the same company does nothing new. A reused store keeps its products, including any example products, and gets the company's website if it had none. The audit log records whether a store was reused.

CSV export

"Export CSV" (Ekspordi CSV) downloads the companies that match the list's current search, filters and order, as leitagu-ettevotted.csv (UTF-8). The columns are:

name,legal_name,registry_code,status,priority,fit,types,segments,website,has_webshop,hq_city,locations,founded_year,employees,employees_year,revenue_eur,revenue_year,owner,next_step,next_step_due,confidence,tags
  • Lists (types, segments, locations, tags) are joined with "|".
  • The owner is the owner's email.
  • Text that a spreadsheet would run as a formula (starting with =, +, @, or - followed by a non-digit) gets a leading apostrophe.