event

Learning Book Published

A learning book was published and is on sale. cna-one's pricing consumer opens a pending price for it in every current and future default price group.

Event Topic: LearningBookKey: id

Overview

Fact: a learning book reached the status PUBLISHED. The payload is a snapshot of the book.

When it is published. CNA OneCNA OneServicev1.0.0Franchise operating system (franchises and employees, pricing, products and learning books, school operations). Publishe...PublishesGrantApplicationAccess, EmployeeCreated +6SubscribesInviteUser, FranchiseCreated +9Ownercna-platformMapRepoView docs, in franchisorUpdateLearningBookStatus, after the status change and its publication history row are written: produceLearningBookStatusEvent picks the event from the stored status, so status in the payload is always PUBLISHED here. Published after the write completes, not inside afterCommit.

What the consumer does. cna-one’s pricing process (priceConsumer, handler syncLearningBookPublishedToPrices):

  1. Loads the default price groups (B2B and B2C) of the price tables that are current or future today, together with the prices they already hold for this book.
  2. No group: logs a warning and stops.
  3. For each group without a live price for the book, prepares a pending price (type FIXED, amount null). A soft-deleted price is recovered instead of duplicated; a live price is left untouched, which makes redelivery harmless.
  4. Upserts the pending prices. Someone then fills the amounts in the price table screen.

Failures are logged and reported to Sentry, never rethrown.

Kafka

Topic (aggregateRoot)LearningBook
Message key (routingKey)payload.id
Contract ownerONE
metadata.eventLearningBookPublished
Consumer grouppricing-price-events

Payload schema

Source of truth

import { LearningBookStatus } from "db/enums/product/LearningBook";
export type LearningBookPayload = {
id: string;
productId: string;
publisherId: string;
edition: number;
protheusId: string;
isbn?: string | null;
url?: string | null;
imageUrl?: string | null;
isDigitalContentAvailable: boolean;
status: LearningBookStatus;
};
class LearningBookPublished extends Event<LearningBookPayload> {
public static owner = "ONE";
public static aggregateRoot = "LearningBook";
public static routingKey = "id";
}

The class exists only in cna-one.

Custom properties

PropertyValue
Contract Ownerx-contract-ownerONE
Kafka Topicx-kafka-topicLearningBook
Message Keyx-message-keyid
Sourcex-sourcecna-one api/app/events/one/learningBook/LearningBookPublished.ts
10 properties
idstring
required

Learning book id (UUID). Kafka message key.

productIdstring
required

Product the edition belongs to (product.products, type LEARNING_BOOK).

publisherIdstring
required

Publisher id (product.publishers).

editioninteger
required

Edition number.

protheusIdstring
required

Id in the Protheus ERP (4 characters).

isbnstring | null

ISBN (13 characters), or null.

urlstring | null

URL of the digital book, or null.

imageUrlstring | null

Cover image URL, or null.

isDigitalContentAvailableboolean
required

Whether digital content is available.

statusstring
required

Publication status (cna-one LearningBookStatus). Matches the event: PUBLISHED, DRAFT or DISCONTINUED; UNDER_REVIEW never reaches the topic.

Allowed values: DRAFT PUBLISHED DISCONTINUED UNDER_REVIEW