@peabody-soft/mbs-model-ts 1.7.1 → 1.9.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.
Files changed (40) hide show
  1. package/dist/Business.js +2 -1
  2. package/dist/Catalog.d.ts +19 -7
  3. package/dist/Catalog.js +119 -39
  4. package/dist/Constants.d.ts +1 -0
  5. package/dist/Constants.js +6 -3
  6. package/dist/Entity.d.ts +1 -0
  7. package/dist/Entity.js +4 -0
  8. package/dist/Enums.d.ts +1 -0
  9. package/dist/Enums.js +1 -0
  10. package/dist/GeneralSettings.d.ts +5 -4
  11. package/dist/GeneralSettings.js +9 -8
  12. package/dist/Item.js +2 -1
  13. package/dist/Package.d.ts +6 -2
  14. package/dist/Package.js +11 -5
  15. package/dist/Price.d.ts +5 -2
  16. package/dist/Price.js +18 -3
  17. package/dist/PriceList.d.ts +13 -0
  18. package/dist/PriceList.js +50 -2
  19. package/dist/Product.d.ts +6 -2
  20. package/dist/Product.js +8 -5
  21. package/dist/ProtoMap.js +60 -68
  22. package/dist/ShoppingList.js +4 -3
  23. package/dist/generated/BusinessSyncOutResponse.d.ts +4 -1
  24. package/dist/generated/Constants.d.ts +0 -4
  25. package/dist/generated/Constants.js +0 -4
  26. package/dist/generated/GeneralSettings.d.ts +5 -4
  27. package/dist/generated/GeneralSettings.js +8 -6
  28. package/dist/generated/Item.d.ts +4 -3
  29. package/dist/generated/Message.d.ts +5 -0
  30. package/dist/generated/OnlineStoreTheme.d.ts +33 -0
  31. package/dist/generated/OnlineStoreTheme.js +38 -0
  32. package/dist/generated/Price.d.ts +9 -0
  33. package/dist/generated/Price.js +9 -1
  34. package/dist/generated/PriceList.d.ts +13 -2
  35. package/dist/generated/ProfileSyncOutRequest.d.ts +16 -15
  36. package/dist/generated/ProfileSyncOutResponse.d.ts +4 -6
  37. package/dist/generated/SalesOrderPayload.d.ts +6 -3
  38. package/dist/index.d.ts +4 -0
  39. package/dist/index.js +2 -2
  40. package/package.json +2 -2
package/dist/Product.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import Item from "./Item";
2
- // A product in the catalog: goods, a service, a raw material or a fixed asset. Built complete
3
- // (photos and packages resolved first), so everything here is readonly.
2
+ // A product in the catalog: goods, a service, a raw material or a fixed asset. Built with its
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, packages) {
5
+ constructor(header, name, description, productCategoryId, isDisabled, _productType, _brand, _isManufacturedByBusiness, _manufacturer, _manufacturerAddress, _taxes, _features, _isForOfflineSaleOnly, _photos) {
6
6
  super(header, name, description, productCategoryId, isDisabled);
7
7
  this._productType = _productType;
8
8
  this._brand = _brand;
@@ -13,8 +13,7 @@ export default class Product extends Item {
13
13
  this._features = _features;
14
14
  this._isForOfflineSaleOnly = _isForOfflineSaleOnly;
15
15
  this._photos = _photos;
16
- // A package that cannot be bought is dropped, whatever the caller passes in
17
- this._packages = Object.freeze(packages.filter((pkg) => pkg.isBuyable));
16
+ this._packages = Object.freeze([]);
18
17
  }
19
18
  // The category this product is in, or Constants.ENTITY_ID_NULL when it is in none
20
19
  get productCategoryId() {
@@ -61,6 +60,10 @@ export default class Product extends Item {
61
60
  get packages() {
62
61
  return this._packages;
63
62
  }
63
+ // Keeps the buyable packages among those given, and drops the rest
64
+ set packages(value) {
65
+ this._packages = Object.freeze(value.filter((pkg) => pkg.isBuyable));
66
+ }
64
67
  // The cheapest final price across variants (what a listing shows as "from"), or null if there
65
68
  // are no variants. Compares final price, since that is what a customer pays. Every variant is
66
69
  // taxed at this product's rates, so comparing prices with taxes gives the same order as
package/dist/ProtoMap.js CHANGED
@@ -13,6 +13,7 @@ import { Entity as proto_Entity } from "./generated/Entity";
13
13
  import { FulfillmentMode as proto_FulfillmentMode } from "./generated/FulfillmentMode";
14
14
  import { Message as proto_Message } from "./generated/Message";
15
15
  import { MessageType as proto_MessageType } from "./generated/MessageType";
16
+ import { OnlineStoreTheme as proto_OnlineStoreTheme } from "./generated/OnlineStoreTheme";
16
17
  import { OrderStatus as proto_OrderStatus } from "./generated/OrderStatus";
17
18
  import { Package as proto_Package } from "./generated/Package";
18
19
  import { PartyPreferencesPayload as proto_PartyPreferencesPayload } from "./generated/PartyPreferencesPayload";
@@ -692,57 +693,39 @@ export function buildBusiness(response) {
692
693
  updatableBusiness.settings = generalSettingsFromProto(generalSettings, countryCode);
693
694
  // The photos of the store itself
694
695
  updatableBusiness.photos = takePhotos(attachmentsByOwner, business.id, attachmentBaseUrl);
695
- // Prices, by the package each applies to. This storefront uses only the MeraBills Online list. A
696
- // business prices a package in several lists, and a price from another list is not what it sells at
697
- // here, so it is skipped. A package has one price in that list. If a second arrives, the first is
698
- // kept.
699
- const pricesByPackage = new Map();
696
+ // The catalog's items, each built alone. Catalog links them and drops what it cannot (a package
697
+ // with no product, a price with no list) and what cannot be bought. Photos go to packages and
698
+ // products here. A tombstone is skipped, and the business is the containment parent of the items
699
+ // that sit directly under it. Catalog parents the rest.
700
+ const prices = [];
700
701
  for (const priceProto of response.prices) {
701
702
  if (isDeletedItem(priceProto.item))
702
703
  continue;
703
- const price = priceFromProto(priceProto);
704
- if (price.priceListId !== MERABILLS_ONLINE_PRICE_LIST_ID)
704
+ prices.push(priceFromProto(priceProto));
705
+ }
706
+ const priceLists = [];
707
+ for (const priceListProto of response.priceLists) {
708
+ if (isDeletedItem(priceListProto.item))
705
709
  continue;
706
- if (!pricesByPackage.has(price.packageId))
707
- pricesByPackage.set(price.packageId, price);
710
+ const priceList = priceListFromProto(priceListProto);
711
+ UpdatableEntity.setParent(priceList, business);
712
+ priceLists.push(priceList);
708
713
  }
709
- // Packages, by the product each belongs to, built with their photos and price. A package that is not
710
- // buyable (disabled, unpriced, or priced with a disabled price) is left out. A product-level filter
711
- // alone would not guarantee that every package of a visible product is enabled.
712
- const packagesByProduct = new Map();
714
+ const packages = [];
713
715
  for (const packageProto of response.packages) {
714
716
  if (isDeletedItem(packageProto.item))
715
717
  continue;
716
- const packageId = getItemId(packageProto.item);
717
- const packagePhotos = takePhotos(attachmentsByOwner, packageId, attachmentBaseUrl);
718
- const pkg = packageFromProto(packageProto, packagePhotos, pricesByPackage.get(packageId) ?? null);
719
- if (!pkg.isBuyable)
720
- continue;
721
- const price = pkg.price;
722
- if (price !== null)
723
- UpdatableEntity.setParent(price, pkg);
724
- const siblings = packagesByProduct.get(pkg.productId);
725
- if (siblings === undefined)
726
- packagesByProduct.set(pkg.productId, [pkg]);
727
- else
728
- siblings.push(pkg);
718
+ const packagePhotos = takePhotos(attachmentsByOwner, getItemId(packageProto.item), attachmentBaseUrl);
719
+ packages.push(packageFromProto(packageProto, packagePhotos));
729
720
  }
730
- // Products, built with their photos and buyable packages, and parented to the business (their
731
- // category only groups them). A product that is not buyable is left out: disabled, sold only offline
732
- // (the server sends those, flagged), or left with no buyable package by the filtering above.
721
+ // A product's category only groups it, so its containment parent is the business
733
722
  const products = [];
734
723
  for (const productProto of response.products) {
735
724
  if (isDeletedItem(productProto.item))
736
725
  continue;
737
- const productId = getItemId(productProto.item);
738
- const packages = packagesByProduct.get(productId) ?? [];
739
- const productPhotos = takePhotos(attachmentsByOwner, productId, attachmentBaseUrl);
740
- const product = productFromProto(productProto, productPhotos, Object.freeze([...packages]), countryCode);
741
- if (!product.isBuyable)
742
- continue;
726
+ const productPhotos = takePhotos(attachmentsByOwner, getItemId(productProto.item), attachmentBaseUrl);
727
+ const product = productFromProto(productProto, productPhotos, countryCode);
743
728
  UpdatableEntity.setParent(product, business);
744
- for (const pkg of product.packages)
745
- UpdatableEntity.setParent(pkg, product);
746
729
  products.push(product);
747
730
  }
748
731
  const productCategories = [];
@@ -753,20 +736,11 @@ export function buildBusiness(response) {
753
736
  UpdatableEntity.setParent(productCategory, business);
754
737
  productCategories.push(productCategory);
755
738
  }
756
- // A storefront sells from the MeraBills Online list only, picked by id since the same sync can
757
- // carry others. The catalog must hold the list the prices above came from. Otherwise a cart would
758
- // name a list that does not contain them.
759
- let priceList = null;
760
- for (const priceListProto of response.priceLists) {
761
- if (isDeletedItem(priceListProto.item))
762
- continue;
763
- if (getItemId(priceListProto.item) !== MERABILLS_ONLINE_PRICE_LIST_ID)
764
- continue;
765
- priceList = priceListFromProto(priceListProto);
766
- UpdatableEntity.setParent(priceList, business);
767
- break;
768
- }
769
- updatableBusiness.catalog = new Catalog(productCategories, products, priceList);
739
+ // A storefront sells from the MeraBills Online list, picked by id because a response can carry
740
+ // other public lists. That list can follow its parent (see PriceList.getPrice).
741
+ const catalog = new Catalog(productCategories, products, packages, priceLists, prices);
742
+ catalog.currentSalePriceListId = MERABILLS_ONLINE_PRICE_LIST_ID;
743
+ updatableBusiness.catalog = catalog;
770
744
  // The orders of this customer, and their party preferences (the cart and the fulfillment mode to
771
745
  // default the next order to). A message of any other payload type is dropped. The business completes
772
746
  // an order by deleting its message, and the server sends that message whole, so the orders include
@@ -787,7 +761,8 @@ export function buildBusiness(response) {
787
761
  let defaultFulfillmentMode = proto_FulfillmentMode.DELIVERY;
788
762
  if (partyPreferences !== null && partyPreferences.payload.oneofKind === "partyPreferences") {
789
763
  // An emptied cart is a message whose payload has no shopping list, which is what placing an order
790
- // leaves. The cart is null then, the same as for a customer who never had one.
764
+ // leaves. A list with no items is the same: the merchant app stores its cart whether or not it holds
765
+ // anything. The cart is null then, the same as for a customer who never had one.
791
766
  cart = cartShoppingListFromProto(partyPreferences.payload.partyPreferences, countryCode);
792
767
  // Taken as the message has it. DELIVERY comes only from the fallback above, even when the message
793
768
  // holds UNSPECIFIED_FULFILLMENT_MODE.
@@ -850,8 +825,9 @@ export function buildShoppingList(message, countryCode) {
850
825
  // fulfillment mode. An existing message is amended, since its payload can carry fields a storefront
851
826
  // cannot read, and dropping them would overwrite that data. Its id is kept, as the server holds the
852
827
  // preferences under it. The derived id is used only when there is nothing to amend.
853
- // A list with no items is pushed as no list, as Java serializeShoppingList returns null below one
854
- // item. An emptied cart and a cart never created look the same on the wire.
828
+ // A list with no items is pushed as no list. The merchant app stores its cart with no items too, and
829
+ // both read as no cart (cartShoppingListFromProto), so an emptied cart, a cart with no items and a cart
830
+ // never created are one state to a storefront.
855
831
  // fulfillmentMode null keeps the existing value, the ordinary case: a storefront treats that field
856
832
  // as the merchant app's data and leaves it alone. createOrder sets it to the mode of the order that
857
833
  // emptied the cart.
@@ -951,11 +927,18 @@ function inPackageIdOrder(list) {
951
927
  deletedItems: [...list.deletedItems].sort(byPackageId),
952
928
  });
953
929
  }
954
- // The list inside a cart message, or absent for an emptied cart
930
+ // The list inside a cart message, or absent for an emptied cart. A list with no items is absent too,
931
+ // as the merchant app stores its cart whether or not it holds anything (see cartShoppingListFromProto)
955
932
  function getCartShoppingList(message) {
956
- return message.payload.oneofKind === "partyPreferences"
957
- ? message.payload.partyPreferences.shoppingList
958
- : undefined;
933
+ if (message.payload.oneofKind !== "partyPreferences")
934
+ return undefined;
935
+ const shoppingList = message.payload.partyPreferences.shoppingList;
936
+ return shoppingList === undefined || holdsNothing(shoppingList) ? undefined : shoppingList;
937
+ }
938
+ // Whether a list on the wire has no items. The items are what is judged, not the counts, as in
939
+ // pushedShoppingList
940
+ function holdsNothing(shoppingList) {
941
+ return shoppingList.existingItems.length === 0 && shoppingList.deletedItems.length === 0;
959
942
  }
960
943
  // A shopping list to push, or absent when it holds nothing - see buildPartyPreferencesMessage.
961
944
  // Emptiness is judged by the items sent, not the counts, for the reason given at shoppingListToProto.
@@ -1119,6 +1102,11 @@ function getItemId(item) {
1119
1102
  function stringFromProto(value) {
1120
1103
  return value === undefined ? null : value;
1121
1104
  }
1105
+ // The enum's zero means no theme was picked. A number the enum has no entry for (a theme that a newer
1106
+ // app added) is kept as it came, so the caller decides what to show.
1107
+ function onlineStoreThemeFromProto(value) {
1108
+ return value === proto_OnlineStoreTheme.UNSPECIFIED_ONLINE_STORE_THEME ? null : value;
1109
+ }
1122
1110
  // The reverse of stringFromProto. An empty string goes out absent too: the two mean the same, and
1123
1111
  // sending one could bring the field back as the other.
1124
1112
  function stringToProto(value) {
@@ -1209,7 +1197,7 @@ function shoppingListFromProto(shoppingList, countryCode) {
1209
1197
  return ShoppingList.fromScaledValues(shoppingList.isFinal, shoppingList.autoAddDeliveryCharge, shoppingList.autoAddServiceCharge, shoppingList.inventoryLocationId, shoppingList.priceListId, shoppingList.totalAmountBeforeDiscount, shoppingList.discount, shoppingList.existingItemCount, shoppingList.deletedItemCount, Object.freeze(shoppingList.existingItems.map((item) => shoppingListItemFromProto(item, countryCode))), Object.freeze(shoppingList.deletedItems.map((item) => shoppingListItemFromProto(item, countryCode))));
1210
1198
  }
1211
1199
  function generalSettingsFromProto(settings, countryCode) {
1212
- return GeneralSettings.fromScaledValues(Object.freeze(settings.paymentMethodDetails.map(paymentMethodDetailFromProto)), stringFromProto(settings.customerServicePhone), settings.isWhatsAppSupported, settings.isSmsSupported, addressListFromProto(settings.businessAddresses), Object.freeze(settings.businessIdentifiers.map(businessIdentifierFromProto)), Object.freeze([...settings.fulfillmentModes]), settings.deliveryCharge, Object.freeze(settings.deliveryChargeTaxes.map((tax) => taxFromProto(tax, countryCode))), settings.freeDeliveryTotal, settings.deliveryRadiusKms, stringFromProto(settings.storeTagline), workingDaysFromProto(settings.workingDays), latLongFromProto(settings.primaryStoreLocation), stringFromProto(settings.googleBusinessCategoryId), stringFromProto(settings.googleBusinessCategoryName), stringFromProto(settings.onlineStoreThemeId), settings.onlineShoppingEnabled);
1200
+ return GeneralSettings.fromScaledValues(Object.freeze(settings.paymentMethodDetails.map(paymentMethodDetailFromProto)), stringFromProto(settings.customerServicePhone), settings.isWhatsAppSupported, settings.isSmsSupported, addressListFromProto(settings.businessAddresses), Object.freeze(settings.businessIdentifiers.map(businessIdentifierFromProto)), Object.freeze([...settings.fulfillmentModes]), settings.deliveryCharge, Object.freeze(settings.deliveryChargeTaxes.map((tax) => taxFromProto(tax, countryCode))), settings.freeDeliveryTotal, settings.deliveryRadiusKms, stringFromProto(settings.storeTagline), workingDaysFromProto(settings.workingDays), latLongFromProto(settings.primaryStoreLocation), stringFromProto(settings.googleBusinessCategoryId), stringFromProto(settings.googleBusinessCategoryName), onlineStoreThemeFromProto(settings.onlineStoreTheme), settings.onlineShoppingEnabled);
1213
1201
  }
1214
1202
  // #endregion
1215
1203
  // #region Entities
@@ -1247,32 +1235,36 @@ function priceListFromProto(priceListProto) {
1247
1235
  function priceFromProto(priceProto) {
1248
1236
  const item = getItem(priceProto.item);
1249
1237
  const entity = getEntity(item.entity);
1250
- return Price.fromScaledValues(toEntityHeader(entity), item.name, stringFromProto(item.description), item.parentItemId, item.isDisabled, priceProto.packageId, priceProto.regularPrice, priceProto.offerPrice);
1238
+ return Price.fromScaledValues(toEntityHeader(entity), item.name, stringFromProto(item.description), item.parentItemId, item.isDisabled, priceProto.packageId, priceProto.regularPrice, priceProto.offerPrice, priceProto.isPlaceholder);
1251
1239
  }
1252
- function packageFromProto(packageProto, photos, price) {
1240
+ function packageFromProto(packageProto, photos) {
1253
1241
  const item = getItem(packageProto.item);
1254
1242
  const entity = getEntity(item.entity);
1255
- return new Package(toEntityHeader(entity), item.name, stringFromProto(item.description), item.parentItemId, item.isDisabled, packageProto.isSoldLoose, packageProto.itemCode, Object.freeze(packageProto.identifiers.map(packageIdentifierFromProto)), dimensionsFromProto(packageProto.dimensions), weightFromProto(packageProto.weight), photos, price);
1243
+ return new Package(toEntityHeader(entity), item.name, stringFromProto(item.description), item.parentItemId, item.isDisabled, packageProto.isSoldLoose, packageProto.itemCode, Object.freeze(packageProto.identifiers.map(packageIdentifierFromProto)), dimensionsFromProto(packageProto.dimensions), weightFromProto(packageProto.weight), photos);
1256
1244
  }
1257
- function productFromProto(productProto, photos, packages, countryCode) {
1245
+ function productFromProto(productProto, photos, countryCode) {
1258
1246
  const item = getItem(productProto.item);
1259
1247
  const entity = getEntity(item.entity);
1260
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)
1261
1249
  stringFromProto(productProto.manufacturer), productProto.manufacturerAddress === undefined
1262
1250
  ? null
1263
- : addressFromProto(productProto.manufacturerAddress), Object.freeze(productProto.taxes.map((tax) => taxFromProto(tax, countryCode))), Object.freeze([...productProto.features]), productProto.forOfflineSaleOnly, photos, packages);
1251
+ : addressFromProto(productProto.manufacturerAddress), Object.freeze(productProto.taxes.map((tax) => taxFromProto(tax, countryCode))), Object.freeze([...productProto.features]), productProto.forOfflineSaleOnly, photos);
1264
1252
  }
1265
1253
  function orderFromProto(message, salesOrder, countryCode) {
1266
1254
  const entity = getEntity(message.entity);
1267
1255
  return Order.fromScaledValues(toEntityHeader(entity), message.senderId, message.status, stringFromProto(message.senderName), stringFromProto(message.senderPhone), salesOrder.status, salesOrder.fulfillmentMode, shoppingListFromProto(salesOrder.shoppingList, countryCode), salesOrder.shoppingListTotal, salesOrder.shoppingListCount, salesOrder.deliveryAddressId, salesOrder.deliveryAddress === undefined ? null : addressFromProto(salesOrder.deliveryAddress), salesOrder.creationDate, stringFromProto(salesOrder.note), salesOrder.paymentReceived);
1268
1256
  }
1269
1257
  // The one part of a cart message a customer is shown. Null when the cart holds nothing, so a cart
1270
- // emptied by placing an order and one never created both give null. The rest of the message is set by
1271
- // the server or read elsewhere: who sent it, how far the business has read it, and the fulfillment
1272
- // mode, which buildBusiness reads as defaultFulfillmentMode.
1258
+ // emptied by placing an order, one never created, and a list with no items (the merchant app stores
1259
+ // its cart even when it is empty, with the properties of the list) all give null. The properties of
1260
+ // a list with no items are not read: a cart is built again from its items. The rest of the message
1261
+ // is set by the server or read elsewhere: who sent it, how far the business has read it, and the
1262
+ // fulfillment mode, which buildBusiness reads as defaultFulfillmentMode.
1273
1263
  function cartShoppingListFromProto(partyPreferences, countryCode) {
1274
1264
  const shoppingList = partyPreferences.shoppingList;
1275
- return shoppingList === undefined ? null : shoppingListFromProto(shoppingList, countryCode);
1265
+ return shoppingList === undefined || holdsNothing(shoppingList)
1266
+ ? null
1267
+ : shoppingListFromProto(shoppingList, countryCode);
1276
1268
  }
1277
1269
  // #endregion
1278
1270
  // #region Photos
@@ -58,9 +58,10 @@ class ShoppingList {
58
58
  get inventoryLocationId() {
59
59
  return this._inventoryLocationId;
60
60
  }
61
- // The id of the price list these prices came from. A storefront sells from
62
- // Constants.MERABILLS_ONLINE_PRICE_LIST_ID, the list in Catalog.priceList, and CartEditor falls
63
- // back to that id when the catalog has no price list.
61
+ // The id of the price list the cart is priced from. A storefront names
62
+ // Constants.MERABILLS_ONLINE_PRICE_LIST_ID, the list in Catalog.priceList, for every line, including
63
+ // one with the amounts of that list's parent. CartEditor falls back to that id when the catalog has
64
+ // no price list.
64
65
  get priceListId() {
65
66
  return this._priceListId;
66
67
  }
@@ -21,7 +21,10 @@ import { AuthTokens } from "./AuthTokens";
21
21
  * Item.parentItemId, Attachment.owningEntityId and Price.packageId, processing the arrays below in
22
22
  * order (parent before child). An absent/empty field means that type has not changed; a tombstone
23
23
  * (updateNumber's update-type bits = Constants.UPDATE_TYPE_DELETED) means the entity, and what it
24
- * owned, was deleted. At most Constants.SYNC_OUT_LIMIT entities arrive together - that many means
24
+ * owned, was deleted; it is sent as it is held, like any entity - but for an item (a product, package, price,
25
+ * price list or product category), which is only its Entity - and a client reads nothing of it but its
26
+ * Entity - but for a Message, which holds the order that the business completed, if it was one (see
27
+ * Message). At most Constants.SYNC_OUT_LIMIT entities arrive together - that many means
25
28
  * call again with the raised cursors.
26
29
  * There is no response, but a 404 (NotFoundException), when the business is not one a storefront can
27
30
  * open: it does not exist or has been deleted, or it does not allow customers to join it. Both are
@@ -242,10 +242,6 @@ export declare enum Constants {
242
242
  * @generated from protobuf enum value: GOOGLE_BUSINESS_CATEGORY_NAME_MAX_LENGTH = 256;
243
243
  */
244
244
  GOOGLE_BUSINESS_CATEGORY_NAME_MAX_LENGTH = 256,
245
- /**
246
- * @generated from protobuf enum value: BUSINESS_ID_MAX_LENGTH = 64;
247
- */
248
- ONLINE_STORE_THEME_ID_MAX_LENGTH = 64,
249
245
  /**
250
246
  * PaymentMethodDetail.data
251
247
  *
@@ -247,10 +247,6 @@ export var Constants;
247
247
  * @generated from protobuf enum value: GOOGLE_BUSINESS_CATEGORY_NAME_MAX_LENGTH = 256;
248
248
  */
249
249
  Constants[Constants["GOOGLE_BUSINESS_CATEGORY_NAME_MAX_LENGTH"] = 256] = "GOOGLE_BUSINESS_CATEGORY_NAME_MAX_LENGTH";
250
- /**
251
- * @generated from protobuf enum value: BUSINESS_ID_MAX_LENGTH = 64;
252
- */
253
- Constants[Constants["ONLINE_STORE_THEME_ID_MAX_LENGTH"] = 64] = "ONLINE_STORE_THEME_ID_MAX_LENGTH";
254
250
  /**
255
251
  * PaymentMethodDetail.data
256
252
  *
@@ -4,6 +4,7 @@ import type { BinaryReadOptions } from "@protobuf-ts/runtime";
4
4
  import type { IBinaryReader } from "@protobuf-ts/runtime";
5
5
  import type { PartialMessage } from "@protobuf-ts/runtime";
6
6
  import { MessageType } from "@protobuf-ts/runtime";
7
+ import { OnlineStoreTheme } from "./OnlineStoreTheme";
7
8
  import { LatLong } from "./LatLong";
8
9
  import { WorkingDays } from "./WorkingDays";
9
10
  import { Tax } from "./Tax";
@@ -122,12 +123,12 @@ export interface GeneralSettings {
122
123
  */
123
124
  googleBusinessCategoryName?: string;
124
125
  /**
125
- * Id of the visual theme applied to the online store
126
- * (at most Constants.ONLINE_STORE_THEME_ID_MAX_LENGTH)
126
+ * Visual theme applied to the online store. UNSPECIFIED_ONLINE_STORE_THEME means no theme is set.
127
+ * A client must treat a number it has no entry for as no theme: a newer app may have added one.
127
128
  *
128
- * @generated from protobuf field: optional string onlineStoreThemeId = 17
129
+ * @generated from protobuf field: com.merabills.storefront.OnlineStoreTheme onlineStoreTheme = 17
129
130
  */
130
- onlineStoreThemeId?: string;
131
+ onlineStoreTheme: OnlineStoreTheme;
131
132
  /**
132
133
  * True if the business has turned online shopping on. The server does not refuse a business that has
133
134
  * not: it is for the client to, once it has read all it is sent (see BusinessSyncOutResponse). A
@@ -2,6 +2,7 @@ import { UnknownFieldHandler } from "@protobuf-ts/runtime";
2
2
  import { WireType } from "@protobuf-ts/runtime";
3
3
  import { reflectionMergePartial } from "@protobuf-ts/runtime";
4
4
  import { MessageType } from "@protobuf-ts/runtime";
5
+ import { OnlineStoreTheme } from "./OnlineStoreTheme";
5
6
  import { LatLong } from "./LatLong";
6
7
  import { WorkingDays } from "./WorkingDays";
7
8
  import { Tax } from "./Tax";
@@ -29,7 +30,7 @@ class GeneralSettings$Type extends MessageType {
29
30
  { no: 14, name: "primaryStoreLocation", kind: "message", T: () => LatLong },
30
31
  { no: 15, name: "googleBusinessCategoryId", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
31
32
  { no: 16, name: "googleBusinessCategoryName", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
32
- { no: 17, name: "onlineStoreThemeId", kind: "scalar", opt: true, T: 9 /*ScalarType.STRING*/ },
33
+ { no: 17, name: "onlineStoreTheme", kind: "enum", T: () => ["com.merabills.storefront.OnlineStoreTheme", OnlineStoreTheme] },
33
34
  { no: 18, name: "onlineShoppingEnabled", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
34
35
  ]);
35
36
  }
@@ -44,6 +45,7 @@ class GeneralSettings$Type extends MessageType {
44
45
  message.deliveryChargeTaxes = [];
45
46
  message.freeDeliveryTotal = 0n;
46
47
  message.deliveryRadiusKms = 0;
48
+ message.onlineStoreTheme = 0;
47
49
  message.onlineShoppingEnabled = false;
48
50
  if (value !== undefined)
49
51
  reflectionMergePartial(this, message, value);
@@ -106,8 +108,8 @@ class GeneralSettings$Type extends MessageType {
106
108
  case /* optional string googleBusinessCategoryName */ 16:
107
109
  message.googleBusinessCategoryName = reader.string();
108
110
  break;
109
- case /* optional string onlineStoreThemeId */ 17:
110
- message.onlineStoreThemeId = reader.string();
111
+ case /* com.merabills.storefront.OnlineStoreTheme onlineStoreTheme */ 17:
112
+ message.onlineStoreTheme = reader.int32();
111
113
  break;
112
114
  case /* bool onlineShoppingEnabled */ 18:
113
115
  message.onlineShoppingEnabled = reader.bool();
@@ -176,9 +178,9 @@ class GeneralSettings$Type extends MessageType {
176
178
  /* optional string googleBusinessCategoryName = 16; */
177
179
  if (message.googleBusinessCategoryName !== undefined)
178
180
  writer.tag(16, WireType.LengthDelimited).string(message.googleBusinessCategoryName);
179
- /* optional string onlineStoreThemeId = 17; */
180
- if (message.onlineStoreThemeId !== undefined)
181
- writer.tag(17, WireType.LengthDelimited).string(message.onlineStoreThemeId);
181
+ /* com.merabills.storefront.OnlineStoreTheme onlineStoreTheme = 17; */
182
+ if (message.onlineStoreTheme !== 0)
183
+ writer.tag(17, WireType.Varint).int32(message.onlineStoreTheme);
182
184
  /* bool onlineShoppingEnabled = 18; */
183
185
  if (message.onlineShoppingEnabled !== false)
184
186
  writer.tag(18, WireType.Varint).bool(message.onlineShoppingEnabled);
@@ -17,9 +17,10 @@ export interface Item {
17
17
  */
18
18
  entity?: Entity;
19
19
  /**
20
- * Id of the parent of this item - the category of a product, the product of a package, or the
21
- * price list of a price - or 0 when it has none. A client rebuilds the catalog hierarchy by
22
- * grouping items on this id, since nothing nests on the wire.
20
+ * Id of the parent of this item - the category of a product, the product of a package, the
21
+ * price list of a price, or the parent price list of a price list - or 0 when it has none. A
22
+ * client rebuilds the catalog hierarchy by grouping items on this id, since nothing nests on the
23
+ * wire.
23
24
  *
24
25
  * @generated from protobuf field: int64 parentItemId = 2
25
26
  */
@@ -13,6 +13,11 @@ import { Entity } from "./Entity";
13
13
  * A message sent to a business: an order (SalesOrderPayload) or a customer's shopping cart
14
14
  * (PartyPreferencesPayload), typed here rather than left as the serialized string Java stores.
15
15
  * MONEY_TRANSFER messages have no payload in this protocol.
16
+ * A message that has been deleted (see Entity.updateNumber) is converted as it is held, as every entity
17
+ * is, deleted or not, but for the items of the catalog. The merchant app completes an order, by fulfilling or cancelling it, by deleting
18
+ * its message, so, a deleted message that carries a sales order is an order that the business has
19
+ * completed, and is the whole of what a customer is shown of it afterwards. A deleted message is not
20
+ * a cart, whatever it carries.
16
21
  *
17
22
  * @generated from protobuf message com.merabills.storefront.Message
18
23
  */
@@ -0,0 +1,33 @@
1
+ /**
2
+ * A visual theme of the online store. The palettes ship with the online store, so a business picks
3
+ * one of these and cannot mix colours. Values match the ids of the corresponding Java enum entries
4
+ * and must never be changed.
5
+ *
6
+ * @generated from protobuf enum com.merabills.storefront.OnlineStoreTheme
7
+ */
8
+ export declare enum OnlineStoreTheme {
9
+ /**
10
+ * Java has no zero value: it treats a theme of zero as not set
11
+ *
12
+ * @generated from protobuf enum value: UNSPECIFIED_ONLINE_STORE_THEME = 0;
13
+ */
14
+ UNSPECIFIED_ONLINE_STORE_THEME = 0,
15
+ /**
16
+ * Deep forest brand, terracotta accent, warm paper
17
+ *
18
+ * @generated from protobuf enum value: FOREST = 1;
19
+ */
20
+ FOREST = 1,
21
+ /**
22
+ * Indigo brand, rust accent, cooler paper
23
+ *
24
+ * @generated from protobuf enum value: INDIGO = 2;
25
+ */
26
+ INDIGO = 2,
27
+ /**
28
+ * Brick brand, amber accent, the warmest paper
29
+ *
30
+ * @generated from protobuf enum value: BRICK = 3;
31
+ */
32
+ BRICK = 3
33
+ }
@@ -0,0 +1,38 @@
1
+ // @ts-nocheck
2
+ // @generated by protobuf-ts 2.11.1 with parameter long_type_bigint
3
+ // @generated from protobuf file "OnlineStoreTheme.proto" (package "com.merabills.storefront", syntax proto3)
4
+ // tslint:disable
5
+ /**
6
+ * A visual theme of the online store. The palettes ship with the online store, so a business picks
7
+ * one of these and cannot mix colours. Values match the ids of the corresponding Java enum entries
8
+ * and must never be changed.
9
+ *
10
+ * @generated from protobuf enum com.merabills.storefront.OnlineStoreTheme
11
+ */
12
+ export var OnlineStoreTheme;
13
+ (function (OnlineStoreTheme) {
14
+ /**
15
+ * Java has no zero value: it treats a theme of zero as not set
16
+ *
17
+ * @generated from protobuf enum value: UNSPECIFIED_ONLINE_STORE_THEME = 0;
18
+ */
19
+ OnlineStoreTheme[OnlineStoreTheme["UNSPECIFIED_ONLINE_STORE_THEME"] = 0] = "UNSPECIFIED_ONLINE_STORE_THEME";
20
+ /**
21
+ * Deep forest brand, terracotta accent, warm paper
22
+ *
23
+ * @generated from protobuf enum value: FOREST = 1;
24
+ */
25
+ OnlineStoreTheme[OnlineStoreTheme["FOREST"] = 1] = "FOREST";
26
+ /**
27
+ * Indigo brand, rust accent, cooler paper
28
+ *
29
+ * @generated from protobuf enum value: INDIGO = 2;
30
+ */
31
+ OnlineStoreTheme[OnlineStoreTheme["INDIGO"] = 2] = "INDIGO";
32
+ /**
33
+ * Brick brand, amber accent, the warmest paper
34
+ *
35
+ * @generated from protobuf enum value: BRICK = 3;
36
+ */
37
+ OnlineStoreTheme[OnlineStoreTheme["BRICK"] = 3] = "BRICK";
38
+ })(OnlineStoreTheme || (OnlineStoreTheme = {}));
@@ -38,6 +38,15 @@ export interface Price {
38
38
  * @generated from protobuf field: int64 offerPrice = 4
39
39
  */
40
40
  offerPrice: bigint;
41
+ /**
42
+ * True when this price has no amounts of its own: the package has the amounts of the price that
43
+ * the parent of the price list has for it. regularPrice and offerPrice are a copy of those that
44
+ * can be out of date, so a client must not use them. Item.isDisabled says whether the package is
45
+ * in this price list. See PriceList.
46
+ *
47
+ * @generated from protobuf field: bool isPlaceholder = 5
48
+ */
49
+ isPlaceholder: boolean;
41
50
  }
42
51
  declare class Price$Type extends MessageType<Price> {
43
52
  constructor();
@@ -10,7 +10,8 @@ class Price$Type extends MessageType {
10
10
  { no: 1, name: "item", kind: "message", T: () => Item },
11
11
  { no: 2, name: "packageId", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },
12
12
  { no: 3, name: "regularPrice", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },
13
- { no: 4, name: "offerPrice", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }
13
+ { no: 4, name: "offerPrice", kind: "scalar", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },
14
+ { no: 5, name: "isPlaceholder", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
14
15
  ]);
15
16
  }
16
17
  create(value) {
@@ -18,6 +19,7 @@ class Price$Type extends MessageType {
18
19
  message.packageId = 0n;
19
20
  message.regularPrice = 0n;
20
21
  message.offerPrice = 0n;
22
+ message.isPlaceholder = false;
21
23
  if (value !== undefined)
22
24
  reflectionMergePartial(this, message, value);
23
25
  return message;
@@ -39,6 +41,9 @@ class Price$Type extends MessageType {
39
41
  case /* int64 offerPrice */ 4:
40
42
  message.offerPrice = reader.int64().toBigInt();
41
43
  break;
44
+ case /* bool isPlaceholder */ 5:
45
+ message.isPlaceholder = reader.bool();
46
+ break;
42
47
  default:
43
48
  let u = options.readUnknownField;
44
49
  if (u === "throw")
@@ -63,6 +68,9 @@ class Price$Type extends MessageType {
63
68
  /* int64 offerPrice = 4; */
64
69
  if (message.offerPrice !== 0n)
65
70
  writer.tag(4, WireType.Varint).int64(message.offerPrice);
71
+ /* bool isPlaceholder = 5; */
72
+ if (message.isPlaceholder !== false)
73
+ writer.tag(5, WireType.Varint).bool(message.isPlaceholder);
66
74
  let u = options.writeUnknownFields;
67
75
  if (u !== false)
68
76
  (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -6,8 +6,19 @@ import type { PartialMessage } from "@protobuf-ts/runtime";
6
6
  import { MessageType } from "@protobuf-ts/runtime";
7
7
  import { Item } from "./Item";
8
8
  /**
9
- * A named list of prices; has no parent, so its own Item.parentItemId is 0. Contains nothing - its
10
- * prices are the Price entities whose Item.parentItemId is this price list's id.
9
+ * A named list of prices. Item.parentItemId is the id of its parent price list, or 0 when it has
10
+ * none. Contains nothing - its prices are the Price entities whose Item.parentItemId is this price
11
+ * list's id.
12
+ *
13
+ * A list with a parent follows it. Only the parent is consulted, never its parent.
14
+ * - A package with no price in the list has the parent's price: its amounts, and it is in the list
15
+ * when that price is enabled.
16
+ * - A price of the list replaces the parent's price, both the amounts and whether it is enabled.
17
+ * - A placeholder (Price.isPlaceholder) replaces only whether the package is enabled. The amounts
18
+ * are the parent's price: the placeholder holds a copy that can be out of date, so a client must
19
+ * not use it.
20
+ * - A placeholder is no price at all when the parent has no price for the package.
21
+ *
11
22
  * Excluded: isPurchasePriceList - a purchase price list is never sent, so the flag would always be
12
23
  * false.
13
24
  *
@@ -34,21 +34,22 @@ export interface ProfileSyncOutRequest {
34
34
  /**
35
35
  * The business to join as a customer, if the caller is not already linked to it. 0 means none, and
36
36
  * anything else has to be the id of a business: one that is not is refused, not ignored.
37
- * A call that carries a valid link token of this business is from a member of it already, and nothing is
38
- * joined: the response is what the cursors above return, as for a call that joins nothing, and it is not
39
- * refused for the business no longer allowing customers to join it. A link token that is not valid is
40
- * refused (401), and one of another business says nothing of this one.
41
- * Otherwise the response always carries the BusinessLink and the Business that a join returns, even
42
- * where the cursors above would not return them.
43
- * An invitation to this business for the caller (looked for by their phone number) takes precedence: it is
44
- * accepted in the role and party that the invitation names, which may be those of a manager or an owner as
45
- * well as of a customer, whether or not the business allows customers to join without an invitation, and
46
- * the invitation is deleted. Only when there is none does the business decide.
47
- * The call fails with 404 (NotFoundException) if there is no such business, or if the caller has no
48
- * invitation to it and it does not allow customers to join it, and the caller does not hold a valid link
49
- * token of it. It is the link token that is tested, and not membership: a member that does not hold one (on
50
- * a new device, say) of a business that has since stopped allowing customers to join is refused in the same
51
- * way, and then the whole call is a 404 - nothing of the profile is returned either, and not only no join.
37
+ * A member of the business is not joined again, and is not refused if the business no longer allows
38
+ * customers to join it. Nothing is changed for a member, so the response is what the cursors above
39
+ * return, as for a call that joins nothing.
40
+ * A call that does join makes a new BusinessLink. It is newer than the link cursor, so the response
41
+ * carries it, and the Business that it names whatever the business cursor is.
42
+ * An invitation to this business for the caller (looked for by their phone number) that names a party takes
43
+ * precedence: the newest one is accepted in the role and party that the invitation names, which may be those
44
+ * of a manager or an owner as well as of a customer, whether or not the business allows customers to join
45
+ * without an invitation, and the invitation is deleted. The call is refused if another member has that party.
46
+ * Only when there is no such invitation does the business decide.
47
+ * Without an invitation the caller joins as a customer: as the customer party of the business that has their
48
+ * phone number, if there is one, else as a new customer party. A caller that was a member before gets a new
49
+ * link and, unless a party has their phone number, a new party.
50
+ * The call fails with 404 (NotFoundException) if there is no such business, or if the caller is not a member,
51
+ * has no invitation to it, and it does not allow customers to join it. The whole call is then a 404:
52
+ * nothing of the profile is returned either.
52
53
  *
53
54
  * @generated from protobuf field: int64 joinBusinessId = 4
54
55
  */