@peabody-soft/mbs-model-ts 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Catalog.d.ts CHANGED
@@ -16,6 +16,8 @@ export default class Catalog {
16
16
  getCategory(productCategoryId: bigint): ProductCategory | null;
17
17
  getProduct(productId: bigint): Product | null;
18
18
  getPackage(packageId: bigint): Package | null;
19
+ getProductForDisplay(productId: bigint): Product | null;
20
+ getPackageForDisplay(packageId: bigint): Package | null;
19
21
  static comparePackages(left: Package, right: Package): number;
20
22
  static compareByName(left: Item, right: Item): number;
21
23
  private static compareNames;
@@ -27,6 +29,8 @@ export default class Catalog {
27
29
  private readonly _allProducts;
28
30
  private readonly _uncategorized;
29
31
  private readonly _candidatePackages;
32
+ private readonly _displayProductMap;
33
+ private readonly _displayPackageMap;
30
34
  private readonly _priceListMap;
31
35
  private _currentSalePriceListId;
32
36
  private _categories;
package/dist/Catalog.js CHANGED
@@ -13,6 +13,7 @@ class Catalog {
13
13
  constructor(categories, products, packages, priceLists, prices) {
14
14
  // Every package that has a product, by that product's id, whether it can be bought or not
15
15
  this._candidatePackages = new Map();
16
+ this._displayPackageMap = new Map();
16
17
  this._priceListMap = new Map();
17
18
  this._currentSalePriceListId = DEFAULT_SALE_PRICE_LIST_ID;
18
19
  // What a customer can reach, rebuilt by applySalePriceList
@@ -31,11 +32,13 @@ class Catalog {
31
32
  const productsById = new Map();
32
33
  for (const product of products)
33
34
  productsById.set(product.id, product);
35
+ this._displayProductMap = productsById;
34
36
  for (const pkg of packages) {
35
37
  const product = productsById.get(pkg.productId);
36
38
  if (product === undefined)
37
39
  continue;
38
40
  UpdatableEntity.setParent(pkg, product);
41
+ this._displayPackageMap.set(pkg.id, pkg);
39
42
  const productPackages = this._candidatePackages.get(product.id);
40
43
  if (productPackages === undefined)
41
44
  this._candidatePackages.set(product.id, [pkg]);
@@ -110,6 +113,25 @@ class Catalog {
110
113
  getPackage(packageId) {
111
114
  return this._packageMap.get(packageId) ?? null;
112
115
  }
116
+ // Like getProduct, but for any product that the server sent, whether it can be bought or not: it
117
+ // is disabled, or it has nothing left to buy. It is for drawing a shopping list that already
118
+ // exists, such as an order that was placed, whose line can name a product that is no longer
119
+ // sold. Do not use it to offer anything for sale. Its packages are not on offer either:
120
+ // Product.packages keeps only the buyable ones, so it is empty for a product that cannot be
121
+ // bought. Null for an unknown id.
122
+ getProductForDisplay(productId) {
123
+ return this._displayProductMap.get(productId) ?? null;
124
+ }
125
+ // Like getPackage, but for any package of a product that the server sent, whether it can be
126
+ // bought or not: it is disabled, it has no enabled price, or its product is disabled. For
127
+ // drawing a shopping list that already exists (see getProductForDisplay), not for offering
128
+ // anything for sale. Package.price is the price in the current sale price list, null when there
129
+ // is none, and disabled when the package is not in that list. Null for an unknown id, and for
130
+ // the four reserved package ids a shopping list uses for its charge and summary lines (see
131
+ // Ids.isReservedPackageId).
132
+ getPackageForDisplay(packageId) {
133
+ return this._displayPackageMap.get(packageId) ?? null;
134
+ }
113
135
  // Display comparator for packages, matching the merchant app's PackageComparator minus the
114
136
  // clauses a storefront cannot exercise (disabled packages and the purchase price list, neither sent)
115
137
  static comparePackages(left, right) {
@@ -143,10 +165,9 @@ class Catalog {
143
165
  return left.offerPrice - right.offerPrice;
144
166
  }
145
167
  // Prices the packages from the current sale price list, then rebuilds what a customer can reach.
146
- // Only a buyable product is part of a catalog: enabled, not sold only offline, with at least one
147
- // buyable package. Any other is left out of products, getProduct and its categories, and its
148
- // packages are unreachable by id. A category with no buyable products is left out too, the dummy
149
- // one included.
168
+ // Only a buyable product is part of a catalog: enabled, with at least one buyable package. Any
169
+ // other is left out of products, getProduct and its categories, and its packages are unreachable
170
+ // by id. A category with no buyable products is left out too, the dummy one included.
150
171
  applySalePriceList() {
151
172
  const salePriceList = this.priceList;
152
173
  const buyableProducts = [];
package/dist/Product.d.ts CHANGED
@@ -14,9 +14,8 @@ export default class Product extends Item {
14
14
  private readonly _manufacturerAddress;
15
15
  private readonly _taxes;
16
16
  private readonly _features;
17
- private readonly _isForOfflineSaleOnly;
18
17
  private readonly _photos;
19
- constructor(header: EntityHeader, name: string, description: string | null, productCategoryId: bigint, isDisabled: boolean, _productType: proto_ProductType, _brand: string | null, _isManufacturedByBusiness: boolean, _manufacturer: string | null, _manufacturerAddress: Address | null, _taxes: ReadonlyArray<Tax>, _features: ReadonlyArray<string>, _isForOfflineSaleOnly: boolean, _photos: ReadonlyArray<Photo>);
18
+ constructor(header: EntityHeader, name: string, description: string | null, productCategoryId: bigint, isDisabled: boolean, _productType: proto_ProductType, _brand: string | null, _isManufacturedByBusiness: boolean, _manufacturer: string | null, _manufacturerAddress: Address | null, _taxes: ReadonlyArray<Tax>, _features: ReadonlyArray<string>, _photos: ReadonlyArray<Photo>);
20
19
  get productCategoryId(): bigint;
21
20
  get productType(): proto_ProductType;
22
21
  get brand(): string | null;
@@ -25,7 +24,6 @@ export default class Product extends Item {
25
24
  get manufacturerAddress(): Address | null;
26
25
  get taxes(): ReadonlyArray<Tax>;
27
26
  get features(): ReadonlyArray<string>;
28
- get isForOfflineSaleOnly(): boolean;
29
27
  get photos(): ReadonlyArray<Photo>;
30
28
  get packages(): ReadonlyArray<Package>;
31
29
  private set packages(value);
package/dist/Product.js CHANGED
@@ -2,7 +2,7 @@ import Item from "./Item";
2
2
  // A product in the catalog: goods, a service, a raw material or a fixed asset. Built with its
3
3
  // photos. Catalog sets its packages, once their prices are known.
4
4
  export default class Product extends Item {
5
- constructor(header, name, description, productCategoryId, isDisabled, _productType, _brand, _isManufacturedByBusiness, _manufacturer, _manufacturerAddress, _taxes, _features, _isForOfflineSaleOnly, _photos) {
5
+ constructor(header, name, description, productCategoryId, isDisabled, _productType, _brand, _isManufacturedByBusiness, _manufacturer, _manufacturerAddress, _taxes, _features, _photos) {
6
6
  super(header, name, description, productCategoryId, isDisabled);
7
7
  this._productType = _productType;
8
8
  this._brand = _brand;
@@ -11,7 +11,6 @@ export default class Product extends Item {
11
11
  this._manufacturerAddress = _manufacturerAddress;
12
12
  this._taxes = _taxes;
13
13
  this._features = _features;
14
- this._isForOfflineSaleOnly = _isForOfflineSaleOnly;
15
14
  this._photos = _photos;
16
15
  this._packages = Object.freeze([]);
17
16
  }
@@ -46,12 +45,6 @@ export default class Product extends Item {
46
45
  get features() {
47
46
  return this._features;
48
47
  }
49
- // True when the business sells this product only offline. The server sends such a product like
50
- // any other, flagged, and this model must not offer it to a customer (see isBuyable). A catalog
51
- // never holds one, so only a hand-built product can report true.
52
- get isForOfflineSaleOnly() {
53
- return this._isForOfflineSaleOnly;
54
- }
55
48
  get photos() {
56
49
  return this._photos;
57
50
  }
@@ -86,11 +79,10 @@ export default class Product extends Item {
86
79
  return true;
87
80
  return false;
88
81
  }
89
- // True when this product is enabled, is not sold only offline, and has at least one variant (it
90
- // keeps only buyable ones). The server filters out draft and non-public products before they
91
- // arrive. isDisabled can change after an item exists and offline-only products are sent flagged,
92
- // so both are checked here.
82
+ // True when this product is enabled and has at least one variant (it keeps only buyable ones).
83
+ // The server filters out draft and non-public products before they arrive. isDisabled can change
84
+ // after an item exists, so it is checked here.
93
85
  get isBuyable() {
94
- return !this.isDisabled && !this._isForOfflineSaleOnly && this._packages.length > 0;
86
+ return !this.isDisabled && this._packages.length > 0;
95
87
  }
96
88
  }
package/dist/ProtoMap.js CHANGED
@@ -1248,7 +1248,7 @@ function productFromProto(productProto, photos, countryCode) {
1248
1248
  return new Product(toEntityHeader(entity), item.name, stringFromProto(item.description), item.parentItemId, item.isDisabled, productProto.productType, stringFromProto(productProto.brand), productProto.isManufacturedByBusiness ?? true, // Absent means true (Product.proto)
1249
1249
  stringFromProto(productProto.manufacturer), productProto.manufacturerAddress === undefined
1250
1250
  ? null
1251
- : addressFromProto(productProto.manufacturerAddress), Object.freeze(productProto.taxes.map((tax) => taxFromProto(tax, countryCode))), Object.freeze([...productProto.features]), productProto.forOfflineSaleOnly, photos);
1251
+ : addressFromProto(productProto.manufacturerAddress), Object.freeze(productProto.taxes.map((tax) => taxFromProto(tax, countryCode))), Object.freeze([...productProto.features]), photos);
1252
1252
  }
1253
1253
  function orderFromProto(message, salesOrder, countryCode) {
1254
1254
  const entity = getEntity(message.entity);
@@ -13,7 +13,7 @@ import { Item } from "./Item";
13
13
  * at most one category (Item.parentItemId, 0 = none); its packages and photos are found the same
14
14
  * way, by parentItemId / owningEntityId.
15
15
  * Excluded: isDraft, isStockKeepingEnabled, isExpiryTrackingEnabled,
16
- * storeProperties, defaultExpiry, classifications, all Translations fields.
16
+ * storeProperties, defaultExpiry, classifications, forOfflineSaleOnly, all Translations fields.
17
17
  *
18
18
  * @generated from protobuf message com.merabills.storefront.Product
19
19
  */
@@ -63,15 +63,6 @@ export interface Product {
63
63
  * @generated from protobuf field: repeated string features = 8
64
64
  */
65
65
  features: string[];
66
- /**
67
- * True when the business sells this product only offline (Java Product.getForOfflineSaleOnly: the product has "available
68
- * online" turned off). The server sends such a product like any other public one, and it is for the client to not show
69
- * it, nor its packages, to a customer, nor let a customer order it (mbs-model's Catalog leaves it out). Absent means
70
- * false: a product that is not offline-only
71
- *
72
- * @generated from protobuf field: bool forOfflineSaleOnly = 9
73
- */
74
- forOfflineSaleOnly: boolean;
75
66
  }
76
67
  declare class Product$Type extends MessageType<Product> {
77
68
  constructor();
@@ -17,8 +17,7 @@ class Product$Type extends MessageType {
17
17
  { no: 5, name: "manufacturer", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
18
18
  { no: 6, name: "manufacturerAddress", kind: "message", T: () => Address },
19
19
  { no: 7, name: "taxes", kind: "message", repeat: 2 /*RepeatType.UNPACKED*/, T: () => Tax },
20
- { no: 8, name: "features", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ },
21
- { no: 9, name: "forOfflineSaleOnly", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
20
+ { no: 8, name: "features", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ }
22
21
  ]);
23
22
  }
24
23
  create(value) {
@@ -26,7 +25,6 @@ class Product$Type extends MessageType {
26
25
  message.productType = 0;
27
26
  message.taxes = [];
28
27
  message.features = [];
29
- message.forOfflineSaleOnly = false;
30
28
  if (value !== undefined)
31
29
  reflectionMergePartial(this, message, value);
32
30
  return message;
@@ -60,9 +58,6 @@ class Product$Type extends MessageType {
60
58
  case /* repeated string features */ 8:
61
59
  message.features.push(reader.string());
62
60
  break;
63
- case /* bool forOfflineSaleOnly */ 9:
64
- message.forOfflineSaleOnly = reader.bool();
65
- break;
66
61
  default:
67
62
  let u = options.readUnknownField;
68
63
  if (u === "throw")
@@ -99,9 +94,6 @@ class Product$Type extends MessageType {
99
94
  /* repeated string features = 8; */
100
95
  for (let i = 0; i < message.features.length; i++)
101
96
  writer.tag(8, WireType.LengthDelimited).string(message.features[i]);
102
- /* bool forOfflineSaleOnly = 9; */
103
- if (message.forOfflineSaleOnly !== false)
104
- writer.tag(9, WireType.Varint).bool(message.forOfflineSaleOnly);
105
97
  let u = options.writeUnknownFields;
106
98
  if (u !== false)
107
99
  (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peabody-soft/mbs-model-ts",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "MeraBills storefront client-side model (TypeScript)",
5
5
  "author": "Peabody Soft",
6
6
  "license": "AGPL-3.0-or-later",
@@ -49,7 +49,7 @@
49
49
  "typescript": "^7.0.2"
50
50
  },
51
51
  "dependencies": {
52
- "@peabody-soft/mbs-protos": "^1.13.0",
52
+ "@peabody-soft/mbs-protos": "^1.14.0",
53
53
  "@protobuf-ts/runtime": "^2.11.1"
54
54
  }
55
55
  }