Group A · IPAL DB
SRD_IPROD
The product
Catalogue, covers, risks and events, limits and deductibles, loadings, pricing factors, the screen, packages, annex types, texts. Maintained through the recommendation-engine UI.
Serdica · IPAL / ABACUS · requirements
What the configurator must do to turn an insurer's product specification into a configuration that quotes, issues and prices correctly. The subject is a Bulstrad product in Serdica IPAL: configuration lives in four separate surfaces, two of them in a different database, and no tool moves a complete product between them. 52 requirements across nine areas, each with the check that proves it. Row counts are measured on PROD, 2026-09-02.
Requirement ids carry the area, not a sequence: SC scope · IN input ·
MD model · AB ABACUS · SY ABACUS→IPAL seed · PR IPAL product · IX
INSIS integration · VF verification · GV governance. MUST
is a release condition; SHOULD is defensible to skip with a stated
reason. Every row names how it is checked, because a requirement nobody can fail is a wish.
Provenance tags mark every line of the product model, and are used throughout this page:
Sections marked + collapse the evidence behind a rule. Open them when you disagree
with the rule — the counts are the argument.
The configurator produces files: a canonical product model, idempotent SQL per part, an acceptance script, a rollback script and a product document. It designs a configuration from a specification. It is not a migration tool, not a data-fix tool, and not an authority on whether the product should exist.
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| SC-1 | MUST | Never execute DDL or DML against any environment — not DEV, not inside a block that rolls back. Auditing, triggers and redo capture the attempt regardless. | No write call in the transcript |
| SC-2 | MUST | Never alter a core table or column without explicit permission. The usual trigger is a product code longer than CFG_POLICY_NO_SEQ.PRODUCT_CODE VARCHAR2(4) — stop and offer the four-digit alternative first. | No ALTER in emitted SQL |
| SC-3 | MUST | Propose the parts and ask which are in scope before writing anything. Group A (IPAL product), B (ABACUS tariff) and C (INSIS integration) are separately commissionable. | Scope confirmed in writing |
| SC-4 | MUST | Stop and ask when the specification is contradictory, silent, or undecidable from the data. A wrong guess about coverage scope, currency or clause mapping is business-visible. | Open questions list is non-empty or explicitly empty |
| SC-5 | SHOULD | Report a defect found in existing configuration rather than reproducing it. Discovering that a live product is wrong is a valid outcome of the work. | Findings section |
A product is not one configuration. It is four, in two databases, with no foreign key between them — so nothing enforces consistency and nothing dictates the order of work. Two of the four have no maintenance screen at all.
Group A · IPAL DB
SRD_IPROD
The product
Catalogue, covers, risks and events, limits and deductibles, loadings, pricing factors, the screen, packages, annex types, texts. Maintained through the recommendation-engine UI.
Group B · IPAL DB
SRD_ANLT
The ABACUS tariff
Versions, covers, LD list, factors, rate files, deployed rulesets. The engine reads only
DEPLOYED; an OPEN version is untestable, not safe.
Group C · IPAL DB
SRD_INTEGR
Rules and the INSIS seam
Field validations, the CFG_MAPPING_* map, and the ABC_*
INSIS→ABACUS proxy — 7 packages, 14 tables, every entry point typed
policy@insis%ROWTYPE. No UI — SQL only. 43 product codes
hardcoded in its PL/SQL; zero in SRD_IPROD.
Group C · INSIS DB
ABC_ACCESS
INSIS-side ABACUS
36 CFG_ABC_* tables on PROD, 32 on TEST. Fires on the IPAL transfer as well as in
INSIS Forms — the surface most often forgotten.
IPAL does not write a finished policy into INSIS. It writes an application and asks INSIS to convert it:
TR_POLICY:685 — ins_bof.pol(…), commented "transfer policy as an application"; the row lands at policy_state = -2TR_POLICY:709 — GEN_APPL_PKG.CONVERT@insis(…)INSIS.USEREXIT_GEN_APPL.Convert:3693 → abc_access.pr_abc.ConvertAppl(…); a false return rejects the conversionPR_ABC.ConvertAppl → abc_lib.CommonPolicyValidation(…, 'CONVERT') unconditionally, then a per-LOB branchUSEREXIT:518/578 call the same package on both premium stages, so the surface is
live for IPAL-originated policies at three points. CFG_ABC_FLD_VALIDATION by stage:
BEFOREPREM 797 rows / 66 products · AFTERPREM 211 / 45 ·
CONVERT 60 / 16. The convert rows are underwriting-authority
gates — reinsurance retention, minimum premium, head-office approval, back-dating.
⚠ TR_POLICY:732–738 sets
l_st := TRUE on a failed convert for every product except 4710, so a rejected
non-motor policy is reported as transferred.
Product 2215 on PROD: 49 factors in PR_PRICING_FACTORS,
29 of them in PPA_FACTORS, and 3 appearing
anywhere in the product's rate files. Even for a factor that appears, the grid carries only the
values that differentiate the rate — so a rate file is a lower bound on the value set,
never the set.
ppaSync carries the skeleton and no rates; it is absent from the
bulstrad-prod and bulstrad-staging branches, and several of its
defaults are wrong (taxRule='SUM' where every live product uses MULT).
TRANSFER_PRODUCTS.CreateProduct — the system's own definition of a product, 91
tables in dependency order — touches neither SRD_ANLT nor ABC_ACCESS.
A product moved by trProduct therefore arrives without its tariff.
A specification is normally a set of files, or a directory of them — a tariff PDF, a cover workbook, a screen mock-up, an email settling one clause, a later revision of one sheet. Each describes a different part or a different aspect, they arrive at different times, and together they will still not contain everything. Treating them as one document is the first way this goes wrong; the second is treating them as independent.
The configurator's first job is to build one reading of the set, say which file is authoritative for which part, and name precisely what no file answers — in a form the author can answer.
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| IN-1 | MUST | Accept a set of files or a directory. Inventory it first: one line per file — name, date, which parts of the product it speaks to, and whether it is a source or a revision of another. | Source inventory at the head of the model |
| IN-1a | MUST | Assign one authoritative file per part. Where two files cover the same part, the later one wins only if it says so; otherwise it is a conflict, not a revision. | Authority column in the source inventory |
| IN-1b | MUST | Reconcile across files rather than within each. A cover priced in the tariff and absent from the cover workbook is a finding, not an oversight to fix silently — and so is the reverse. | Cross-document reconciliation table |
| IN-1c | MUST | Restate the merged specification in its own terms before proposing anything, and name every place the set is silent. | Restatement reviewed by the author |
| IN-2 | MUST | Read a rate as the document writes it and convert once, explicitly. 0.08 % of sum insured is 0.0008 in a rate file; getting this wrong is a factor of 100. | Rate-file spot check against the tariff |
| IN-3 | MUST | Treat every risk the specification names as a cover to configure, including those it does not price. | Cover count = risk count in the model |
| IN-4 | SHOULD | Record the source document, its date and its version alongside the model, and cite the clause for any value that a reader would otherwise have to trust. | Model header |
| IN-5 | MUST | Implement a specification as written even when it appears wrong — a double-counted loading, a discount the spec calls manual — and raise the concern as a numbered question. Changing a price without a trace is worse than an odd price. | Open questions list |
The same facts have to be stated in four places. Authored four times, they drift, and the drift is invisible until a premium comes out wrong. So the model is written first and once, and every emitted file declares which section of it it projects.
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| MD-1 | MUST | Write one model file covering the whole product before emitting any SQL. Every generated file names the model section it projects. | File headers |
| MD-2 | MUST | Tag every line with its provenance — SPEC SYS DEC, as defined above. An untagged line is an unreviewable line. | No unmarked line |
| MD-3 | MUST | Collect every DEC line into a numbered open-questions list. A model with no DEC lines means the gaps were filled silently — that is the failure this practice exists to prevent. | Question count > 0 |
| MD-4 | MUST | Freeze the shared vocabulary in the model: cover codes, factor codes, factor names, and the ANLT_VALUE strings a rate grid must match character for character. | Vocabulary section is complete before part files |
| MD-5 | SHOULD | Record a genuine asymmetry between surfaces as a deliberate difference rather than harmonising it in one file and forgetting the other. | Asymmetry list |
| MD-6 | MUST | Change the model first and regenerate what depends on it; never patch a projection alone. | Counts in the acceptance script derive from the model |
"One character off and the grid resolves on (Other) — a different
premium, with no message."
— on why the vocabulary is frozen before either surface is written
A rate grid's row and column headers carry the factor name, not the code, and its
cells match PR_PRICING_FACTOR_VALUES.ANLT_VALUE as literal strings. On a new product the
cheapest way to remove the whole class of mismatch is to set
PRICING_FACTOR_NAME = PRICING_FACTOR_CODE, so code, header token and request key are one
string with nothing left to keep in sync.
◆ marks a gate — work does not proceed past it, and nothing is reported complete until every gate has been passed.
SRD_INTEGR packages to need a dev change, not a config row."Both reported five packages. A check that agrees with itself cannot detect an absent step."
— why step 10 is a gate and not advice
A product was handed over as complete with its pricing reconciled to the cent, and it could not produce a quote: the packaging layer had never been wired, and the check that should have caught it measured the work against the plan that produced it. Verification that derives from the model can only prove internal consistency. Only the running system can prove the product works.
The configuration is a new design answering this specification. The 57 live products are the best available evidence about what the schema allows, what the code reads and what vocabulary is already in use — and they are also, sometimes, wrong, dated or half-finished. Look before choosing; do not let what you find make the choice.
| What you observed | Authority |
|---|---|
The schema says so — type, length, NOT NULL, CHECK, FK | Binds. COVER_CODE VARCHAR2(15) is a limit, not a habit |
| The backend or the UI branches on the value | Binds functionally — confirm in the source, not from the row count |
| A naming grammar or house style | Follow it unless you have a reason; say so in the model when you deviate |
| One column tracking another in 100 % of rows | A correlation, probably a rule — verify before relying on it or breaking it |
| A split across live products | What others chose, not what yours should be — decide from the spec and tag it DEC |
| One or two rows | Dirt or a defect — not a precedent, and often worth reporting |
Cover codes. 692 of 692 live codes match ^[A-Z0-9_]+$;
VARCHAR2(15) NOT NULL, lengths 2–15. Uppercase English — a whole word when
it fits in 15 characters (THEFT, FLOOD,
LIABILITY, EARTHQUAKE), an abbreviation only when it does not
(BI_TERRORISM).
Limits and deductibles follow a grammar that carries meaning:
DEDUCTIBLE* percent · DEDUCTIBLEV* absolute value ·
LIMIT_AG_* aggregate · LIMIT_EV_* per event ·
LIMIT_PE_* / LIMIT_KG_* per person, per kilogram ·
FRANCH, PML, LPD_*, LBI_*. An aggregate
legal-expenses limit is LIMIT_AG_LEGEXP.
Message keys are product-first — P7008_PF_IV_HOME, not
PF_7008_IV_HOME — so one LIKE 'P7008\_%' shows the product's whole
vocabulary and one statement removes it. The tables carry no PRODUCT_CODE, so a
generic key lets a new product silently inherit another's wording.
| Column | Live shape | Consequence |
|---|---|---|
| SR_MESSAGES.MSG | Latin-only on 12 858 / 14 612 (88 %) | The parent row carries the English / technical wording |
| SR_MESSAGES_LNG.LANGUAGE | BG on 14 512 / 14 516 | One BG row per key. An EN row here has never been written |
| SR_MESSAGES.MSG_TYPE | MESSAGE 13 759 · ERROR 829 · LABEL 22 | Labels are MESSAGE. LABEL is not the convention despite its name |
| SR_MESSAGES.MSG_PURPOSE | NULL on 98.8 % | Names the owning subsystem (BOT, BETH) — leave NULL |
| PR_PRICING_FACTORS.SALE_STAGE | POL 1 977 / 1 977 | One row per factor. QT exists only on DEV |
| PR_PRICING_FACTORS.DATATYPE | LIST 1 038 · NUMBER 259 · IV_COV 245 · … | Drives the UI field generator. STRING has 2 rows — use TEXT |
| PR_PRICING_FACTORS.VALUE_SOURCE | POV 84 % | The rest are C# PascalCase EF paths — pc.SrObjects.ObjCar.EngineType |
| PR_BASIC_LD.SEP_ACCOUNT | tracks LD_TYPE 1 465 / 1 465 | LD⇒N, TAX⇒Y — derive it |
| PR_BASIC_LD.LD_SIGN | +1 1 000 · −1 465 | The sign, not the type, separates loading from discount |
| PR_BASIC_PRODUCTS.LOB | ten free-text spellings | No convention at all — one value has a Cyrillic Е and is misspelled |
OBJECT_CODE VARCHAR2(20). 37 values live in
SRD_CUST.SR_OBJECTS.OBJECT_TYPE, bound to INSIS by
SRD_INTEGR.CFG_MAPPING_OBJECT_TYPES. The large ones: CAR 466 908,
PROP 49 084, HOME 42 904, CONTENT 39 747,
CARGO 18 116, GRPPA 8 304.
ANIMAL — farm and productive animals: cow, horse, sheep,
goat, pig, poultry. Live on product 3510 as INSURED_OBJECT with
OBJECT_NUM ← NUM_INS_OBJ.PET — companion animals: cat, dog and the like.
Does not exist yet — absent from both the 37 live types and the mapping
table. A pet product must create it, and if group C is in scope it also needs an INSIS object
model and an insr_type.| Object | DEV | TEST | PROD |
|---|---|---|---|
| PR_PRICING_FACTORS.UI_REQUIRED | exists, NOT NULL | exists | column absent |
| SALE_STAGE = 'QT' | 23 products / 254 rows | 0 | 0 |
| PR_CONSISTENCY_CHECKS | table absent | — | 52 rows |
| INSIS + ABC_ACCESS | absent | present | present |
| The transfer chain | only TR_POLICY | present | present |
DEV is where abandoned ideas (QT) and not-yet-arrived ones
(UI_REQUIRED) both live. Product 8000 / ДЗО work and anything touching
SRD_HLT goes to QA; general configuration goes to TEST.
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| AB-1 | MUST | Emit one rate file per rated cover, with rates as fractions. Cells are <FACTOR> in (value) bands with a final <FACTOR> (Other); rows and columns carry factor names. | Hand-computed premium for one risk |
| AB-2 | MUST | Configure a cover the spec does not price with rate 0 rather than omitting it, in both PR_BASIC_COVERS and PPA_PRODUCT_COVERS. | Cover counts agree across surfaces |
| AB-3 | MUST | Leave SELECTED='Y' and CHANGEABLE='Y' so an underwriter can price a zero-rated cover at policy or application time. | Manual premium accepted in the UI |
| AB-4 | MUST | State the version's EFFECTIVE_DATE and TEMPLATE_CODE explicitly. Version selection is ORDER BY version_id DESC among DEPLOYED rows — the highest id wins, not the latest date. | Version query returns the intended row |
| AB-5 | MUST | State the composition rule per product: Sum or Multiple, and the order. The order is not cosmetic. | Worked example in the product document |
| AB-6 | SHOULD | Exercise the tariff on its own — before a single IPAL row exists — and reconcile one premium against the tariff document by hand. | Reconciliation table |
1300 × 1.05 × 1.30 × 0.90 − (1300 × 0.10) = 1467 · 1300 × 0.90 × 1.05 × 1.30 × 0.90 = 1437
— the same base premium, the same four factors, two orders of application
Mixing a Sum-composed discount with Multiple-composed ones puts 30 EUR between two defensible readings of one tariff. This is why AB-5 exists: "which discounts apply" is never the whole question — in what order, and composed how is the rest of it, and it is a per-product decision that must be written down.
Once the tariff exists, part of the IPAL product can be written from it rather than typed again. Measured across the 63 products ABACUS knows on PROD, that part is real but narrow: it covers three of the twelve parts and roughly one configuration row in seven. It is therefore specified as a seed — a one-time write at creation, not a standing synchronisation.
| Object | In IPAL | ABACUS knows | Coverage | IPAL-only | ABACUS-only |
|---|---|---|---|---|---|
| Covers | 547 | 538 | 98.4 % | 9 | 290 |
| Loadings & taxes | 415 | 380 | 91.6 % | 35 | 181 |
| Pricing factors | 1 443 | 638 | 44.2 % | 805 | 210 |
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| SY-1 | MUST | Run once, at creation, and emit SQL like every other part. It is a seed, not a running sync — re-running it later would overwrite decisions IPAL is the only owner of. | Seed file carries the model section and a generation timestamp |
| SY-2 | MUST | Seed only what ABACUS actually owns: cover codes and their OBJECT_CODE (537 of 538 shared covers agree), the loading/tax list with LD_CODE, LD_TYPE, LD_SIGN, and the factor skeleton (code, name, datatype). | Column-by-column list in the seed file header |
| SY-3 | MUST | Never invent COVER_TYPE. ABACUS has no equivalent of COV/OPT, and mandatory-versus-optional is a commercial decision — every seeded cover arrives tagged DEC. | No seeded cover reaches SQL without a confirmed COVER_TYPE |
| SY-4 | MUST | Filter the ABACUS-only rows rather than importing them: 290 covers and 210 factors exist in ABACUS and not in IPAL. Most are engine-internal or per-clause splits; each one is a question, not a row. | Rejected-rows list in the seed report |
| SY-5 | MUST | Report the seed's own coverage per product before it is trusted. It ranges from 78 % of the factor set on 2200 to 11 % on 4800 — the average tells you nothing about the product in front of you. | Per-product coverage line in the seed report |
| SY-6 | MUST | State plainly, in the same report, that the seed writes none of the nine remaining parts, and give their live row counts so the remaining work is visible. | The "not seeded" table below appears in every seed report |
| Part | Rows | Why ABACUS cannot supply it |
|---|---|---|
| PR_PRICING_FACTOR_VALUES | 2 639 | ABACUS stores the values that differentiate a rate, never the value set an operator picks from |
| PR_BASIC_COVER_DEF | 2 278 | Limits and deductibles are policy terms; the engine sees only their effect on price |
| LB_OFFER_COVERS | 1 541 | Packaging is a commercial construct with no rating meaning |
| CFG_FLD_VALIDATION | 530 | Field rules belong to the integration layer, not to pricing |
| PR_BASIC_COVER_RISKS | 320 | Perils are the wording of the cover, invisible to a rate |
| LB_OFFERS | 289 | See packaging — and this is the layer whose absence let a product reconcile to the cent and fail to quote |
| PR_BASIC_COVER_EVENTS | 216 | Claim events, same reason as perils |
| PR_ANNEX_TYPES | 37 | Endorsement types are a lifecycle concern |
| PR_BASIC_PRODUCT_DOCUMENTS | 20 | Print configuration |
Plus, with no row count because they are not per-product tables: every SR_MESSAGES
label and translation, CFG_POLICY_NO_SEQ, the roles and routes that make the product
reachable, and the whole screen layer — UI_GROUP, UI_ORDER,
POLICY_TABLE, VALUE_SOURCE, DEFAULT_VALUE. A factor seeded
from ABACUS arrives with a code, a name and a datatype, and nothing that puts it on a screen or
tells the backend where to read it.
| Target | Seeded from ABACUS | Left empty or decided |
|---|---|---|
| PR_BASIC_PRODUCTS | BASIC_PRODUCT_CODE, LOB | GENERIC_NAME, VALID_FROM/VALID_TO |
| PR_BASIC_COVERS | COVER_CODE, OBJECT_CODE | COVER_TYPE DEC, LIABILITY, COVER_ORDER, validity |
| PR_BASIC_LD | LD_CODE, LD_TYPE, LD_SIGN | SEP_ACCOUNT (derive from LD_TYPE), NCB, FINST, REFUNDABLE, cover-vs-product level |
| PR_PRICING_FACTORS | PRICING_FACTOR_CODE, PRICING_FACTOR_NAME, DATATYPE, QT_REQUIRED | PRICING_TYPE, POLICY_TABLE, VALUE_SOURCE, UI_FLAG, UI_ORDER, UI_GROUP, DEFAULT_VALUE, COVER_CODE, OBJECT_CODE, SALE_STAGE |
CALC_ORDER on the ABACUS side looks like COVER_ORDER and is not: one
is the sequence the engine prices in, the other is the sequence an operator reads. Seeding one
from the other produces a screen ordered by arithmetic.
98 % of the covers, 44 % of the factors, and none of the nine parts that make the product reachable.
— why this is specified as a seed and not as a synchronisation
The word matters. A sync implies the two sides can be kept in agreement, which invites a
second run later — and a second run would overwrite COVER_TYPE,
UI_GROUP and every other column IPAL alone owns. A seed is a one-time head
start that removes typing, not judgement: it fills the skeleton, tags what it could not decide, and
leaves the twelve-part completeness check exactly where it was.
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| PR-1 | MUST | Configure all twelve parts a reachable product needs, not only those the spec mentions: catalogue, covers, risks and events, limits, loadings, factors and values, screen, packages, annex types, texts, print documents, roles and routing. | Completeness script, one count per surface |
| PR-2 | MUST | Read TRANSFER_PRODUCTS.CreateProduct as the maintained definition of "a product" — 91 tables in dependency order — rather than any prose list, this one included. | Part list reconciled against the package |
| PR-3 | MUST | Allocate every globally unique key deliberately: product code, tariff file name, CFG_ID, MSG_ID, question id, print REP_ID. They collide across products. | Uniqueness check per key space |
| PR-4 | MUST | Create a carrying SR_MESSAGES row for every label — MSG_ID is a hard FK, and the translation cache is built by enumerating the parent table. A key with no parent never reaches the UI. | Orphan-key query returns zero |
| PR-5 | MUST | Supply sequence values explicitly. There are no triggers and no identity columns on these tables. | SQL review |
| PR-6 | SHOULD | Reuse an existing shared code rather than minting a near-duplicate; a new code in a shared register needs a stated reason. | Vocabulary section of the model |
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| IX-1 | MUST | Confirm the product code can exist in INSIS before promising a transfer. HT_INSR_TYPE holds only the bands 11 · 22 · 33 · 34 · 35 · 36 · 38 · 47 · 48 · 59, and CFG_MAPPING_PRODUCT_CODES has exactly one row — so by default the IPAL code is the INSIS insr_type. | Band check against HT_INSR_TYPE |
| IX-1a | MUST | Not configure SRD_INTEGR.ABC_* for an IPAL-only product. It is the INSIS→ABACUS proxy (7 packages, 14 tables, every entry point typed policy@insis%ROWTYPE); IPAL calls the engine directly from the backend. It matters only when the product must also be priced from the INSIS side. | The request map is empty for a group A+B product, deliberately |
| IX-2 | MUST | Configure ABC_ACCESS.CFG_ABC_FLD_VALIDATION and CFG_ABC_OFFICE_VALIDATION when group C is in scope. They run on the IPAL transfer, not only in INSIS Forms. | Convert-stage rules listed in the model |
| IX-3 | MUST | Say plainly which of the 15 product-aware SRD_INTEGR packages need a new branch. That is a dev change on the Ablera process, not a configuration row. | Dev-change list |
| IX-4 | MUST | Raise a Change Request for any INSIS code or user-exit change. Manual data corrections on specific policies do not need one; code does. | CR raised |
| IX-5 | SHOULD | Verify the transfer end to end rather than trusting its return value — a failed conversion is reported as success for every product except 4710. | INSIS policy_state after transfer |
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| VF-1 | MUST | Ship an acceptance script with four parts: completeness per surface, deliberate omissions, cross-layer agreement, and the manual test. | Script runs read-only and reports counts |
| VF-2 | MUST | Derive expected counts from the model, so a changed decision surfaces as a failing count rather than a silent inconsistency. | Counts traceable to model sections |
| VF-3 | MUST | Ship a rollback script that removes exactly what was added, in reverse dependency order. | Rollback reviewed against the emitted SQL |
| VF-4 | MUST | Prove one premium in the running system and reconcile it by hand against the tariff. Internal agreement is not proof. | Screenshot or quote id plus the arithmetic |
| VF-5 | MUST | State every deliberate omission explicitly, with its reason, rather than letting a zero count read as an oversight. | Omissions section of the acceptance script |
| VF-6 | SHOULD | Publish a product document: what was configured, what was decided, what remains open, how to undo it. | Document exists and is indexed |
Product models and product documents use the insurance terms below, and the configurator maps each one onto its column rather than inventing a synonym. Getting the word right is how a business reader and a database reader stay in the same conversation.
| Term | Means | Column |
|---|---|---|
| Base premium | The rating-table output, before anything is applied. One row per cover. | PREM_TYPE='BASEPREM' |
| Written premium | Base premium after loadings and discounts. | PREM_TYPE='WRITTENPREM' |
| Loading / discount | An uplift or reduction. The sign distinguishes them. | LD_TYPE='LD', LD_SIGN ±1 |
| Tax / fee | Kept separately from premium; each is refundable or not, and first-instalment or spread. | LD_TYPE='TAX' |
| Insured value | The sum insured. Its currency is the policy currency. | POL_OBJECT_VALUES 'IV' |
| Short rate | A non-proportional rate for sub-annual periods: raises short premiums, cuts early refunds. | SHORT_AMNT |
| Earned / unearned premium | The elapsed and remaining parts of the period. UPR = GWP − EP. | computed |
| Write-off | Unearned premium. Base: annual premium less non-refundable items. | — |
| Refund | Unearned paid premium. Base: instalments actually paid, less non-refundable items. A different number from the write-off. | — |
| Annex | An endorsement. A premium change appends a negative row; it never edits the old one. | POL_ANNEXES |
| Deductible / limit | Per cover; percent or absolute, aggregate or per event. | PR_BASIC_COVER_DEF |
| Id | Level | Requirement | Verified by |
|---|---|---|---|
| GV-1 | MUST | Use these terms in the model, the product document and any customer-facing reply, and name the column beside the term whenever both readings matter. | Document review |
| GV-2 | MUST | Never call IPAL or INSIS "the core" — both are policy administration systems. Name them. | Document review |
| GV-3 | MUST | Show the currency code with every monetary value. Amounts are stored in main units, and EUR is the default — older policies may be BGN or USD. | Grep for bare numerics in the product document |
| GV-4 | SHOULD | Record a newly measured convention, or a defect found in an existing product, where the next run will read it — not only in the deliverable. | Knowledge or memory entry |
"The document is a design intent, not a description of the running system."
— on the premium specification the vocabulary comes from
The source it is drawn from carries seventeen recorded defects, two of which contradict PROD
outright: it specifies CHANGEABLE='N' for base premium, where all 7 035 157 rows ever
written carry 'Y'; and its field mapping lists 18 of the 22 live columns, omitting
REFUNDABLE and MANUALLY_CORRECTED — the two the manual-premium rule depends
on. Take the vocabulary from it; check the columns against the database.
PR_BASIC_LD.LD_TYPE permits FEE; across 1 465 rows it is never used.
SALE_STAGE permits QT; PROD and TEST hold none. MSG_TYPE
permits LABEL; 22 rows carry it. Being the first product to use a permitted value is
allowed — doing it without noticing is the failure.
Counts derived from the model detect drift between projections. They cannot detect a step that was never in the model. Only a rendered quote reconciled by hand against the tariff closes that gap, which is why it is a gate.
The two are coupled by code and by name, not by constraint, so nothing in the database says
which is written first. What must precede both is the model's frozen vocabulary. After that,
default to ABACUS first — rates are the only never-derivable artefact, they carry the longest
lead time, and PR_BASIC_LD derives from the ABACUS LD list rather than the reverse.
genRuleTable requires stage DONE or CONFIRMED plus an
EFFECTIVE_DATE, then writes RATING_TABLE_FILES per version. A tariff
edited but not deployed changes nothing; a tariff deployed to the wrong version changes the wrong
product. One file set can feed N deployments.
Rate files hold fractions. Product 2215 carries 0.007 and 0.028 at
BP_RATE_DIM='P'. A percentage copied from a tariff document without conversion
produces a premium a hundred times too large, and it will still render.
Named so that nobody assumes otherwise: executing configuration against a database; migrating a
product between environments (trProduct carries neither the tariff nor the INSIS-side
ABACUS configuration — budget both separately); INSIS code and user-exit changes, which need a
Change Request; IPAL backend and UI changes, which are the Ablera dev process; pricing policy — the
configurator implements a tariff, it does not judge one; and the commercial decision of whether the
product should be built.