UNPKG

@twofistedjustice/square-pie

Version:

an easy to use class based chainable interface for the Square API.

529 lines (507 loc) 17.2 kB
const Catalog_Object_Super = require("./catalog_object_abstract_super"); const { nanoid } = require("nanoid"); const { auto_set_appointment_service } = require("../pie_defaults"); const { arrayify, clone_object, shazam_is_boolean, shazam_is_integer, shazam_max_length, shazam_max_length_array, } = require("./utilities"); const { isHexColor } = require("validator"); const man = "Creates a Catalog Item. Every Item must have at least one Item Variation (that's a different Core Class)\n" + "You can pass an id as a constructor argument. If you choose not to do so, a temporary one with a leading '#temp_id_' will be\n" + "generated by nanoid to 8 characters.\n If you wish to change it later, do so before adding any Item Variations. You can\n" + "change it by calling make().id() to change it to a non-leading-# id, or by calling make().temp_id() which adds a '#temp_id_' for you.\n" + "This class follows standard Pie syntax using .make(). You can add variation using `make().variations(variation.fardel)`\n" + "or skip make() and just call the setter `.variations = variation.fardel`\n" + "https://developer.squareup.com/reference/square_2021-12-15/objects/CatalogItem"; /** * {@link https://developer.squareup.com/reference/square_2021-12-15/objects/CatalogItem | **-------> Link To Square Docs <-------**} * @class Catalog_Item * @param {string} id - Optional. A temporary id will be assigned if you omit this. * */ class Catalog_Item extends Catalog_Object_Super { _display_name = "Catalog_Item"; _last_verified_square_api_version = "2021-12-15"; _help = this.display_name + ": " + man; constructor(id = "#temp_id_" + nanoid(8)) { super(); this.configuration = { maximums: { name: 512, description: 4096, abbreviation: 24, item_options: 6, }, }; this._fardel = { id: id, present_at_all_locations: undefined, // bool present_at_location_ids: undefined, //[str] type: "ITEM", item_data: { name: undefined, description: undefined, abbreviation: undefined, category_id: undefined, // add a property to configuration so user doesn't have to deal with id codes? label_color: undefined, available_online: undefined, available_for_pickup: undefined, available_electronically: undefined, tax_ids: undefined, // => array of strings modifier_list_info: undefined, // [modifier, ...] variations: undefined, // [item_variation, ...] product_type: auto_set_appointment_service ? "APPOINTMENTS_SERVICE" : "REGULAR", skip_modifier_screen: undefined, //defaults to false item_options: undefined, // => array of objects sort_name: undefined, // supported in Japan only }, }; } // GETTERS get fardel() { if ( !Array.isArray(this._fardel.item_data.variations) || this._fardel.item_data.variations.length < 1 ) { throw new Error( "Items must have at least one variation or Square will reject the request." ); } return this._fardel; } get type() { return this._fardel.type; } get name() { return this._fardel.item_data.name; } get description() { return this._fardel.item_data.description; } get abbreviation() { return this._fardel.item_data.abbreviation; } get category_id() { return this._fardel.item_data.category_id; } get label_color() { return this._fardel.item_data.label_color; } get available_online() { return this._fardel.item_data.available_online; } get available_for_pickup() { return this._fardel.item_data.available_for_pickup; } get available_electronically() { return this._fardel.item_data.available_electronically; } get tax_ids() { return this._fardel.item_data.tax_ids; } get modifier_list_info() { return this._fardel.item_data.modifier_list_info; } get variations() { return this._fardel.item_data.variations; } get product_type() { return this._fardel.item_data.product_type; } get skip_modifier_screen() { return this._fardel.item_data.skip_modifier_screen; } get item_options() { return this._fardel.item_data.item_options; } get sort_name() { return this._fardel.item_data.sort_name; } // SETTERS set name(str) { let caller = "name"; if ( shazam_max_length( str, this.configuration.maximums.name, this.display_name, caller ) ) { this._fardel.item_data.name = str; } } set description(str) { let caller = "description"; if ( shazam_max_length( str, this.configuration.maximums.description, this.display_name, caller ) ) { this._fardel.item_data.description = str; } } set abbreviation(str) { let caller = "abbreviation"; if ( shazam_max_length( str, this.configuration.maximums.abbreviation, this.display_name, caller ) ) { this._fardel.item_data.abbreviation = str; } } set label_color(hex) { if (!isHexColor(hex)) { throw new Error( `label_color must be a valid hex color. /"${hex}/" is not a valid hex color.` ); } this._fardel.item_data.label_color = hex; } set available_online(bool) { this._fardel.item_data.available_online = bool; } set available_for_pickup(bool) { this._fardel.item_data.available_for_pickup = bool; } set available_electronically(bool) { this._fardel.item_data.available_electronically = bool; } set category_id(id) { this._fardel.item_data.category_id = id; } set tax_ids(id) { arrayify(this._fardel.item_data, "tax_ids", this._display_name); this._fardel.item_data.tax_ids.push(id); } set modifier_list_info(obj) { // has one required value -- the sub-property modifier_overrides also has one required value // check for presence of modifier_list_id // throw error if not // check for presence of modifier_overrides.modifier_id // throw error if parent is present but required child is not arrayify(this._fardel.item_data, "modifier_list_info"); this._fardel.item_data.modifier_list_info.push(obj); } // item_variation id should be "#item.name" + "item_variation.name" set variations(obj) { // An item must have at least one variation. // If user didn't add an id, create an id for the variation by combining name fields // the ID is mentioned in the UPSERT docs if (obj.item_id === undefined || obj.item_id === "") { // obj.item_id = `#${this.name}_${obj.item_variation_data.name}`; obj.item_id = this.id; } arrayify(this._fardel.item_data, "variations", this.display_name); if (obj.item_variation_data.item_id !== this.id) { obj.item_variation_data.item_id = this.id; } // if either property is set, change product_type to appointment if ( obj.item_variation_data.available_for_booking !== undefined || obj.item_variation_data.service_duration !== undefined ) { this.product_type = "APPOINTMENTS_SERVICE"; } this._fardel.item_data.variations.push(obj); } set product_type(val) { this._fardel.item_data.product_type = val; } set skip_modifier_screen(bool) { if (shazam_is_boolean(bool, this._display_name, "skip_modifier_screen")) { this._fardel.item_data.skip_modifier_screen = bool; } } set item_options(id) { arrayify(this._fardel.item_data, "item_options", this._display_name); if ( shazam_max_length_array( this._fardel.item_data.item_options, this.configuration.item_options, this._display_name, "item_options" ) ) { this._fardel.item_data.item_options.push({ item_option_id: id }); } } set sort_name(str) { // Square uses the regular name field as default this._fardel.item_data.sort_name = str; } // PRIVATE METHODS /** * {@link https://developer.squareup.com/reference/square_2021-12-15/enums/CatalogItemProductType | Link To Square Docs}<br> * * #enum_product_type * Enumerated methods set specific values from a limited set of allowable values defined by Square. * For each value, a sub-method will exist that is the lowercase version of that value. There may also * exist abbreviated aliases. * * Enumerated methods are usually called by other functions and set the value on the object on which * the calling function operates. * @typedef {function} Catalog_Item.enum_product_type * @private * @abstract * @memberOf Catalog_Item * @property regular() sets value to "REGULAR" * @property appointments_service() sets value to "APPOINTMENTS_SERVICE" * @property appointment() alias of appointments_service * @property appt() alias of appointments_service * @example * If you were allowed to choose from the set ["GOOD", "BAD", "UGLY"] in order to set the * value of `clint` on the object 'western' * * vyMar.make_western().clint.().good() => const spaghetti = {western : {clint: "GOOD"}} * */ #enum_product_type(calling_this) { return { self: this, regular: function () { this.self.product_type = "REGULAR"; return calling_this; }, appointments_service: function () { this.self.product_type = "APPOINTMENTS_SERVICE"; return calling_this; }, appointment: function () { return this.appointments_service(); }, appt: function () { return this.appointments_service(); }, }; } // MAKE METHODS /** * {@link https://developer.squareup.com/reference/square_2021-12-15/objects/CatalogItemModifierListInfo | Link To Square Docs}<br> * make_modifier_list() builds a compliant modifier_list_Info object. To use the 'view' method you must set the function * to a variable and call the method on the variable. If you don't do this, it will return an un-constructed object. * * Sub-Method names are exactly the same as the property names listed * in the Square docs. There may be additional methods and/or shortened aliases of other methods. * * You should read the generated docs as: * method_name(arg) {type} description of arg * * @typedef {function} Catalog_Item.make_modifier_list * @method * @public * @memberOf Catalog_Item * @property modifier_list_id(id) {string<id>} - * @property modifier_overrides(id,bool) {string|boolean} - boolean defaults to false * @property min_selected_modifiers(int32) {number} -must be an integer * @property max_selected_modifiers(int32) {number} -must be an integer * @property enabled(bool) {boolean} - * @property clear() - clears your entries * @property view() - returns the catalog_modifier_list object under construction * @property add() - adds a copy of the constructed catalog_modifier_list to the array and calls clear() * @example * You must use parentheses with every call to make and with every sub-method. If you have to make a lot * of calls from different lines, it will reduce your tying and improve readability to set make() to a * variable. * * let make = myVar.make(); * make.gizmo() * make.gremlin() * //is the same as * myVar.make().gizmo().gremlin() * */ make_modifier_list() { const name = this.display_name + ".make_modifier_list"; let catalog_modifier_list = { modifier_list_id: undefined, modifier_overrides: undefined, min_selected_modifiers: undefined, max_selected_modifiers: undefined, enabled: undefined, }; let reinitialize = function () { for (let property in catalog_modifier_list) { catalog_modifier_list[property] = undefined; } }; return { self: this, modifier_list_id: function (id) { catalog_modifier_list.modifier_list_id = id; return this; }, modifier_overrides: function (id, bool = false) { if (shazam_is_boolean(bool, name, "modifier_overrides")) { catalog_modifier_list.modifier_overrides = { modifier_id: id, on_by_default: bool, }; } return this; }, min_selected_modifiers: function (int32) { if (shazam_is_integer(int32, name, "min_selected_modifiers")) { catalog_modifier_list.min_selected_modifiers = int32; } return this; }, max_selected_modifiers: function (int32) { if (shazam_is_integer(int32, name, "max_selected_modifiers")) { catalog_modifier_list.max_selected_modifiers = int32; } return this; }, enabled: function (bool = true) { if (shazam_is_boolean(bool, name, "enabled")) { catalog_modifier_list.enabled = bool; } return this; }, clear: function () { reinitialize(); }, view: function () { return catalog_modifier_list; }, add: function () { this.self.modifier_list_info = clone_object(catalog_modifier_list); this.clear(); }, }; } /** * make() method of Catalog_Item * * Sub-Method names are exactly the same as the property names listed * in the Square docs. There may be additional methods and/or shortened aliases of other methods. * * You should read the generated docs as: * method_name(arg) {type} description of arg * * @typedef {function} Catalog_Item.make * @method * @public * @memberOf Catalog_Item * @property id(id) {string<id>} - * @property temp_id(temp_id) {string} - will concatenate the argument to "#temp_id_" * @property present_at_all_locations() * @property present_at_all_locations_ids(id) {boolean} - * @property name(str) {string} - * @property description(str) {string} - * @property abbreviation(str) {string} - * @property label_color(hex) {string} - a hexadecimal color * @property available_online(bool) {boolean} * @property available_for_pickup(bool) {boolean} * @property available_electronically(bool) {boolean} * @property category_id(id) {string<id>} - * @property tax_ids(id) {string<id>} - * @property modifier_list_info(mod) {object} a modifier list object * @property variations(obj) {object} - an item_variation object * @property skip_modifier_screen(bool) {boolean} * @property item_options(bool) {boolean} * @property sort_name() * @property {Enumerated} item_options() * @example * You must use parentheses with every call to make and with every sub-method. If you have to make a lot * of calls from different lines, it will reduce your tying and improve readability to set make() to a * variable. * * let make = myVar.make(); * make.gizmo() * make.gremlin() * //is the same as * myVar.make().gizmo().gremlin() * */ make() { return { self: this, id: function (id) { this.self.id = id; return this; }, temp_id: function (temp_id) { this.self.id = "#temp_id_" + temp_id; return this; }, present_at_all_locations: function (bool) { this.self.present_at_all_locations = bool; return this; }, present_at_all_locations_ids: function (id) { this.self.present_at_location_ids = id; return this; }, name: function (str) { this.self.name = str; return this; }, description: function (str) { this.self.description = str; return this; }, abbreviation: function (str) { this.self.abbreviation = str; return this; }, label_color: function (hex) { this.self.label_color = hex; return this; }, available_online: function (bool) { this.self.available_online = bool; return this; }, available_for_pickup: function (bool) { this.self.available_for_pickup = bool; return this; }, available_electronically: function (bool) { this.self.available_electronically = bool; return this; }, category_id: function (id) { this.self.category_id = id; return this; }, tax_ids: function (id) { this.self.tax_ids = id; return this; }, modifier_list_info: function (mod) { this.self.modifier_list_info = mod; return this; }, variations: function (obj) { this.self.variations = obj; return this; }, skip_modifier_screen: function (bool) { this.self.skip_modifier_screen = bool; return this; }, item_options: function (id) { this.self.item_options = id; return this; }, sort_name: function (str) { this.self.sort_name = str; return this; }, product_type: function () { return this.self.#enum_product_type(this); }, }; } } module.exports = Catalog_Item;