add product variation class to api package

This commit is contained in:
Ron Rennick 2021-02-26 11:25:46 -04:00
parent 65443d923b
commit 533feb7713
8 changed files with 308 additions and 100 deletions

View File

@ -1,9 +1,7 @@
import { Model } from '../../model';
import { MetaData, PostStatus } from '../../shared-types';
import { AbstractProductData } from './data';
import { PostStatus } from '../../shared-types';
import {
CatalogVisibility,
ProductAttribute,
ProductImage,
ProductTerm,
ProductLinks,
} from '../shared';
@ -16,7 +14,7 @@ export type ProductSearchParams = { search: string };
/**
* The base for all product types.
*/
export abstract class AbstractProduct extends Model {
export abstract class AbstractProduct extends AbstractProductData {
/**
* The name of the product.
*
@ -31,34 +29,6 @@ export abstract class AbstractProduct extends Model {
*/
public readonly slug: string = '';
/**
* The permalink of the product.
*
* @type {string}
*/
public readonly permalink: string = '';
/**
* The Id of the product.
*
* @type {number}
*/
public readonly id: number = 0;
/**
* The parent Id of the product.
*
* @type {number}
*/
public readonly parentId: number = 0;
/**
* The menu order assigned to the product.
*
* @type {number}
*/
public readonly menuOrder: number = 0;
/**
* The GMT datetime when the product was created.
*
@ -87,20 +57,6 @@ export abstract class AbstractProduct extends Model {
*/
public readonly shortDescription: string = '';
/**
* The product's full description.
*
* @type {string}
*/
public readonly description: string = '';
/**
* The product's SKU.
*
* @type {string}
*/
public readonly sku: string = '';
/**
* An array of the categories this product is in.
*
@ -115,13 +71,6 @@ export abstract class AbstractProduct extends Model {
*/
public readonly tags: readonly ProductTerm[] = [];
/**
* Indicates whether or not the product is currently able to be purchased.
*
* @type {boolean}
*/
public readonly isPurchasable: boolean = true;
/**
* Indicates whether or not the product should be featured.
*
@ -129,20 +78,6 @@ export abstract class AbstractProduct extends Model {
*/
public readonly isFeatured: boolean = false;
/**
* The attributes for the product.
*
* @type {ReadonlyArray.<ProductAttribute>}
*/
public readonly attributes: readonly ProductAttribute[] = [];
/**
* The images for the product.
*
* @type {ReadonlyArray.<ProductImage>}
*/
public readonly images: readonly ProductImage[] = [];
/**
* Indicates whether or not the product should be visible in the catalog.
*
@ -234,13 +169,6 @@ export abstract class AbstractProduct extends Model {
*/
public readonly relatedIds: Array<number> = [];
/**
* The extra metadata for the product.
*
* @type {ReadonlyArray.<MetaData>}
*/
public readonly metaData: readonly MetaData[] = [];
/**
* The products links.
*

View File

@ -0,0 +1,152 @@
import { Model } from '../../model';
import { MetaData, PostStatus } from '../../shared-types';
import {
ProductAttribute,
ProductImage,
} from '../shared';
/**
* Base product data.
*/
export abstract class AbstractProductData extends Model {
/**
* The permalink of the product.
*
* @type {string}
*/
public readonly permalink: string = '';
/**
* The Id of the product.
*
* @type {number}
*/
public readonly id: number = 0;
/**
* The parent Id of the product.
*
* @type {number}
*/
public readonly parentId: number = 0;
/**
* The menu order assigned to the product.
*
* @type {number}
*/
public readonly menuOrder: number = 0;
/**
* The GMT datetime when the product was created.
*
* @type {Date}
*/
public readonly created: Date = new Date();
/**
* The GMT datetime when the product was last modified.
*
* @type {Date}
*/
public readonly modified: Date = new Date();
/**
* The product's current post status.
*
* @type {PostStatus}
*/
public readonly postStatus: PostStatus = '';
/**
* The product's full description.
*
* @type {string}
*/
public readonly description: string = '';
/**
* The product's SKU.
*
* @type {string}
*/
public readonly sku: string = '';
/**
* Indicates whether or not the product is currently able to be purchased.
*
* @type {boolean}
*/
public readonly isPurchasable: boolean = true;
/**
* The attributes for the product.
*
* @type {ReadonlyArray.<ProductAttribute>}
*/
public readonly attributes: readonly ProductAttribute[] = [];
/**
* The images for the product.
*
* @type {ReadonlyArray.<ProductImage>}
*/
public readonly images: readonly ProductImage[] = [];
// @todo: remove price properties once https://github.com/woocommerce/woocommerce/issues/28885 is merged.
/**
* The current price of the product.
*
* @type {string}
*/
public readonly price: string = '';
/**
* The rendered HTML for the current price of the product.
*
* @type {string}
*/
public readonly priceHtml: string = '';
/**
* The regular price of the product when not discounted.
*
* @type {string}
*/
public readonly regularPrice: string = '';
/**
* Indicates whether or not the product is currently on sale.
*
* @type {boolean}
*/
public readonly onSale: boolean = false;
/**
* The price of the product when on sale.
*
* @type {string}
*/
public readonly salePrice: string = '';
/**
* The GMT datetime when the product should start to be on sale.
*
* @type {Date|null}
*/
public readonly saleStart: Date | null = null;
/**
* The GMT datetime when the product should no longer be on sale.
*
* @type {Date|null}
*/
public readonly saleEnd: Date | null = null;
/**
* The extra metadata for the product.
*
* @type {ReadonlyArray.<MetaData>}
*/
public readonly metaData: readonly MetaData[] = [];
}

View File

@ -1,5 +1,6 @@
export * from './common';
export * from './cross-sell';
export * from './data';
export * from './delivery';
export * from './inventory';
export * from './sales-tax';

View File

@ -1,3 +1,4 @@
export * from './abstract';
export * from './shared';
export * from './simple-product';
export * from './variation';

View File

@ -220,6 +220,13 @@ export class ProductLinks {
*/
public readonly self: readonly ProductLinkItem[] = [];
/**
* The link to the parent.
*
* @type {ReadonlyArray.<ProductLinkItem>}
*/
public readonly up?: readonly ProductLinkItem[] = [];
/**
* Creates a new product link list.
*

View File

@ -6,16 +6,22 @@
*/
export type StockStatus = 'instock' | 'outofstock' | 'onbackorder' | string
/**
* Base product properties.
*/
export type ProductDataUpdateParams = 'created' | 'postStatus'
| 'id' | 'permalink' | 'price' | 'priceHtml'
| 'description' | 'sku' | 'attributes' | 'images'
| 'regularPrice' | 'salePrice' | 'saleStart' | 'saleEnd'
| 'metaData' | 'menuOrder' | 'parentId' | 'links';
/**
* Properties common to all product types.
*/
export type ProductCommonUpdateParams = 'name' | 'slug' | 'created' | 'postStatus' | 'shortDescription'
| 'id' | 'permalink' | 'price' | 'priceHtml' | 'type'
| 'description' | 'sku' | 'categories' | 'tags' | 'isFeatured'
| 'attributes' | 'images' | 'catalogVisibility' | 'allowReviews'
| 'regularPrice' | 'salePrice' | 'saleStart' | 'saleEnd'
| 'metaData' | 'menuOrder' | 'parentId' | 'relatedIds' | 'upsellIds'
| 'links' | 'relatedIds' | 'menuOrder' | 'parentId';
export type ProductCommonUpdateParams = 'name' | 'slug' | 'shortDescription'
| 'categories' | 'tags' | 'isFeatured' | 'averageRating' | 'numRatings'
| 'catalogVisibility' | 'allowReviews' | 'upsellIds' | 'type'
& ProductDataUpdateParams;
/**
* Cross sells property.

View File

@ -0,0 +1,83 @@
import {
AbstractProductData,
IProductDelivery,
IProductInventory,
IProductSalesTax,
IProductShipping,
} from './abstract';
import {
ProductLinks,
Taxability,
ProductDownload,
StockStatus,
BackorderStatus,
} from './shared';
/**
* The base for the product variation object.
*/
export class ProductVariation extends AbstractProductData implements
IProductDelivery,
IProductInventory,
IProductSalesTax,
IProductShipping {
/**
* @see ./abstracts/delivery.ts
*/
public readonly isVirtual: boolean = false;
public readonly isDownloadable: boolean = false;
public readonly downloads: readonly ProductDownload[] = [];
public readonly downloadLimit: number = -1;
public readonly daysToDownload: number = -1;
public readonly purchaseNote: string = '';
/**
* @see ./abstracts/inventory.ts
*/
public readonly onePerOrder: boolean = false;
public readonly trackInventory: boolean = false;
public readonly remainingStock: number = -1;
public readonly stockStatus: StockStatus = ''
public readonly backorderStatus: BackorderStatus = BackorderStatus.Allowed;
public readonly canBackorder: boolean = false;
public readonly isOnBackorder: boolean = false;
/**
* @see ./abstracts/sales-tax.ts
*/
public readonly taxStatus: Taxability = Taxability.ProductAndShipping;
public readonly taxClass: string = '';
/**
* @see ./abstracts/shipping.ts
*/
public readonly weight: string = '';
public readonly length: string = '';
public readonly width: string = '';
public readonly height: string = '';
public readonly requiresShipping: boolean = false;
public readonly isShippingTaxable: boolean = false;
public readonly shippingClass: string = '';
public readonly shippingClassId: number = 0;
/**
* The variation links.
*
* @type {ReadonlyArray.<ProductLinks>}
*/
public readonly links: ProductLinks = {
collection: [ { href: '' } ],
self: [ { href: '' } ],
up: [ { href: '' } ],
};
/**
* Creates a new product variation instance with the given properties
*
* @param {Object} properties The properties to set in the object.
*/
public constructor( properties?: Partial< ProductVariation > ) {
super();
Object.assign( this, properties );
}
}

View File

@ -12,6 +12,7 @@ import {
} from '../../../framework';
import {
AbstractProduct,
AbstractProductData,
IProductCrossSells,
IProductDelivery,
IProductInventory,
@ -108,13 +109,13 @@ function createProductDownloadTransformer(): ModelTransformer< ProductDownload >
}
/**
* Creates a transformer for the shared properties of all products.
* Creates a transformer for the base product property data.
*
* @param {string} type The product type.
* @param {Array.<ModelTransformation>} transformations Optional transformers to add to the transformer.
* @return {ModelTransformer} The created transformer.
*/
export function createProductTransformer< T extends AbstractProduct >(
export function createProductDataTransformation< T extends AbstractProductData >(
type: string,
transformations?: ModelTransformation[],
): ModelTransformer< T > {
@ -132,8 +133,6 @@ export function createProductTransformer< T extends AbstractProduct >(
'date_on_sale_to',
],
),
new ModelTransformerTransformation( 'categories', ProductTerm, createProductTermTransformer() ),
new ModelTransformerTransformation( 'tags', ProductTerm, createProductTermTransformer() ),
new ModelTransformerTransformation( 'attributes', ProductAttribute, createProductAttributeTransformer() ),
new ModelTransformerTransformation( 'images', ProductImage, createProductImageTransformer() ),
new ModelTransformerTransformation( 'metaData', MetaData, createMetaDataTransformer() ),
@ -142,19 +141,13 @@ export function createProductTransformer< T extends AbstractProduct >(
created: PropertyType.Date,
modified: PropertyType.Date,
isPurchasable: PropertyType.Boolean,
isFeatured: PropertyType.Boolean,
onSale: PropertyType.Boolean,
saleStart: PropertyType.Date,
saleEnd: PropertyType.Date,
allowReviews: PropertyType.Boolean,
averageRating: PropertyType.Integer,
numRatings: PropertyType.Integer,
totalSales: PropertyType.Integer,
parentId: PropertyType.Integer,
menuOrder: PropertyType.Integer,
permalink: PropertyType.String,
priceHtml: PropertyType.String,
relatedIds: PropertyType.Integer,
},
),
new KeyChangeTransformation< AbstractProduct >(
@ -162,24 +155,16 @@ export function createProductTransformer< T extends AbstractProduct >(
created: 'date_created_gmt',
modified: 'date_modified_gmt',
postStatus: 'status',
shortDescription: 'short_description',
isPurchasable: 'purchasable',
isFeatured: 'featured',
catalogVisibility: 'catalog_visibility',
regularPrice: 'regular_price',
onSale: 'on_sale',
salePrice: 'sale_price',
saleStart: 'date_on_sale_from_gmt',
saleEnd: 'date_on_sale_to_gmt',
allowReviews: 'reviews_allowed',
averageRating: 'average_rating',
numRatings: 'rating_count',
metaData: 'meta_data',
totalSales: 'total_sales',
parentId: 'parent_id',
menuOrder: 'menu_order',
priceHtml: 'price_html',
relatedIds: 'related_ids',
links: '_links',
},
),
@ -188,6 +173,51 @@ export function createProductTransformer< T extends AbstractProduct >(
return new ModelTransformer( transformations );
}
/**
* Creates a transformer for the shared properties of all products.
*
* @param {string} type The product type.
* @param {Array.<ModelTransformation>} transformations Optional transformers to add to the transformer.
* @return {ModelTransformer} The created transformer.
*/
export function createProductTransformer< T extends AbstractProduct >(
type: string,
transformations?: ModelTransformation[],
): ModelTransformer< T > {
if ( ! transformations ) {
transformations = [];
}
transformations.push(
new ModelTransformerTransformation( 'categories', ProductTerm, createProductTermTransformer() ),
new ModelTransformerTransformation( 'tags', ProductTerm, createProductTermTransformer() ),
new PropertyTypeTransformation(
{
isFeatured: PropertyType.Boolean,
allowReviews: PropertyType.Boolean,
averageRating: PropertyType.Integer,
numRatings: PropertyType.Integer,
totalSales: PropertyType.Integer,
relatedIds: PropertyType.Integer,
},
),
new KeyChangeTransformation< AbstractProduct >(
{
shortDescription: 'short_description',
isFeatured: 'featured',
catalogVisibility: 'catalog_visibility',
allowReviews: 'reviews_allowed',
averageRating: 'average_rating',
numRatings: 'rating_count',
totalSales: 'total_sales',
relatedIds: 'related_ids',
},
),
);
return createProductDataTransformation< T >( type, transformations );
}
export function createProductCrossSellsTransformation(): ModelTransformation[] {
const transformations = [
new PropertyTypeTransformation(