Browse Source

feat(core): Store TaxRate value as decimal type

Fixes #234. This change stores the TaxRate.value as a `decimal` type to allow for decimal percentage value for tax rates. In the GraphQL API the value is now type `Float`.

BREAKING CHANGE: The `TaxRate.value` column type in the database has been changed from `int` to `decimal`. You will need to perform a migration to update this column and depending on your database type, you may need to manually edit the migration script in order to preserve the old values.
Michael Bromley 6 years ago
parent
commit
1aea1b50d2

+ 3 - 3
packages/admin-ui/src/app/common/generated-types.ts

@@ -562,7 +562,7 @@ export type CreateTaxCategoryInput = {
 export type CreateTaxRateInput = {
   name: Scalars['String'],
   enabled: Scalars['Boolean'],
-  value: Scalars['Int'],
+  value: Scalars['Float'],
   categoryId: Scalars['ID'],
   zoneId: Scalars['ID'],
   customerGroupId?: Maybe<Scalars['ID']>,
@@ -3294,7 +3294,7 @@ export type TaxRate = Node & {
   updatedAt: Scalars['DateTime'],
   name: Scalars['String'],
   enabled: Scalars['Boolean'],
-  value: Scalars['Int'],
+  value: Scalars['Float'],
   category: TaxCategory,
   zone: Zone,
   customerGroup?: Maybe<CustomerGroup>,
@@ -3537,7 +3537,7 @@ export type UpdateTaxCategoryInput = {
 export type UpdateTaxRateInput = {
   id: Scalars['ID'],
   name?: Maybe<Scalars['String']>,
-  value?: Maybe<Scalars['Int']>,
+  value?: Maybe<Scalars['Float']>,
   enabled?: Maybe<Scalars['Boolean']>,
   categoryId?: Maybe<Scalars['ID']>,
   zoneId?: Maybe<Scalars['ID']>,

+ 1 - 1
packages/common/src/generated-shop-types.ts

@@ -2177,7 +2177,7 @@ export type TaxRate = Node & {
     updatedAt: Scalars['DateTime'];
     name: Scalars['String'];
     enabled: Scalars['Boolean'];
-    value: Scalars['Int'];
+    value: Scalars['Float'];
     category: TaxCategory;
     zone: Zone;
     customerGroup?: Maybe<CustomerGroup>;

+ 3 - 3
packages/common/src/generated-types.ts

@@ -561,7 +561,7 @@ export type CreateTaxCategoryInput = {
 export type CreateTaxRateInput = {
   name: Scalars['String'],
   enabled: Scalars['Boolean'],
-  value: Scalars['Int'],
+  value: Scalars['Float'],
   categoryId: Scalars['ID'],
   zoneId: Scalars['ID'],
   customerGroupId?: Maybe<Scalars['ID']>,
@@ -3251,7 +3251,7 @@ export type TaxRate = Node & {
   updatedAt: Scalars['DateTime'],
   name: Scalars['String'],
   enabled: Scalars['Boolean'],
-  value: Scalars['Int'],
+  value: Scalars['Float'],
   category: TaxCategory,
   zone: Zone,
   customerGroup?: Maybe<CustomerGroup>,
@@ -3489,7 +3489,7 @@ export type UpdateTaxCategoryInput = {
 export type UpdateTaxRateInput = {
   id: Scalars['ID'],
   name?: Maybe<Scalars['String']>,
-  value?: Maybe<Scalars['Int']>,
+  value?: Maybe<Scalars['Float']>,
   enabled?: Maybe<Scalars['Boolean']>,
   categoryId?: Maybe<Scalars['ID']>,
   zoneId?: Maybe<Scalars['ID']>,

+ 62 - 3
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -561,7 +561,7 @@ export type CreateTaxCategoryInput = {
 export type CreateTaxRateInput = {
     name: Scalars['String'];
     enabled: Scalars['Boolean'];
-    value: Scalars['Int'];
+    value: Scalars['Float'];
     categoryId: Scalars['ID'];
     zoneId: Scalars['ID'];
     customerGroupId?: Maybe<Scalars['ID']>;
@@ -3146,7 +3146,7 @@ export type TaxRate = Node & {
     updatedAt: Scalars['DateTime'];
     name: Scalars['String'];
     enabled: Scalars['Boolean'];
-    value: Scalars['Int'];
+    value: Scalars['Float'];
     category: TaxCategory;
     zone: Zone;
     customerGroup?: Maybe<CustomerGroup>;
@@ -3384,7 +3384,7 @@ export type UpdateTaxCategoryInput = {
 export type UpdateTaxRateInput = {
     id: Scalars['ID'];
     name?: Maybe<Scalars['String']>;
-    value?: Maybe<Scalars['Int']>;
+    value?: Maybe<Scalars['Float']>;
     enabled?: Maybe<Scalars['Boolean']>;
     categoryId?: Maybe<Scalars['ID']>;
     zoneId?: Maybe<Scalars['ID']>;
@@ -5091,6 +5091,39 @@ export type UpdateStockMutation = { __typename?: 'Mutation' } & {
     updateProductVariants: Array<Maybe<{ __typename?: 'ProductVariant' } & VariantWithStockFragment>>;
 };
 
+export type TaxRateFragment = { __typename?: 'TaxRate' } & Pick<
+    TaxRate,
+    'id' | 'name' | 'value' | 'enabled'
+> & {
+        zone: { __typename?: 'Zone' } & Pick<Zone, 'id' | 'name'>;
+        category: { __typename?: 'TaxCategory' } & Pick<TaxCategory, 'id' | 'name'>;
+        customerGroup: Maybe<{ __typename?: 'CustomerGroup' } & Pick<CustomerGroup, 'id' | 'name'>>;
+    };
+
+export type GetTaxRatesQueryVariables = {};
+
+export type GetTaxRatesQuery = { __typename?: 'Query' } & {
+    taxRates: { __typename?: 'TaxRateList' } & Pick<TaxRateList, 'totalItems'> & {
+            items: Array<{ __typename?: 'TaxRate' } & TaxRateFragment>;
+        };
+};
+
+export type GetTaxRateQueryVariables = {
+    id: Scalars['ID'];
+};
+
+export type GetTaxRateQuery = { __typename?: 'Query' } & {
+    taxRate: Maybe<{ __typename?: 'TaxRate' } & TaxRateFragment>;
+};
+
+export type CreateTaxRateMutationVariables = {
+    input: CreateTaxRateInput;
+};
+
+export type CreateTaxRateMutation = { __typename?: 'Mutation' } & {
+    createTaxRate: { __typename?: 'TaxRate' } & TaxRateFragment;
+};
+
 export type DeleteZoneMutationVariables = {
     id: Scalars['ID'];
 };
@@ -6292,6 +6325,32 @@ export namespace UpdateStock {
     export type UpdateProductVariants = VariantWithStockFragment;
 }
 
+export namespace TaxRate {
+    export type Fragment = TaxRateFragment;
+    export type Zone = TaxRateFragment['zone'];
+    export type Category = TaxRateFragment['category'];
+    export type CustomerGroup = NonNullable<TaxRateFragment['customerGroup']>;
+}
+
+export namespace GetTaxRates {
+    export type Variables = GetTaxRatesQueryVariables;
+    export type Query = GetTaxRatesQuery;
+    export type TaxRates = GetTaxRatesQuery['taxRates'];
+    export type Items = TaxRateFragment;
+}
+
+export namespace GetTaxRate {
+    export type Variables = GetTaxRateQueryVariables;
+    export type Query = GetTaxRateQuery;
+    export type TaxRate = TaxRateFragment;
+}
+
+export namespace CreateTaxRate {
+    export type Variables = CreateTaxRateMutationVariables;
+    export type Mutation = CreateTaxRateMutation;
+    export type CreateTaxRate = TaxRateFragment;
+}
+
 export namespace DeleteZone {
     export type Variables = DeleteZoneMutationVariables;
     export type Mutation = DeleteZoneMutation;

+ 1 - 1
packages/core/e2e/graphql/generated-e2e-shop-types.ts

@@ -2177,7 +2177,7 @@ export type TaxRate = Node & {
     updatedAt: Scalars['DateTime'];
     name: Scalars['String'];
     enabled: Scalars['Boolean'];
-    value: Scalars['Int'];
+    value: Scalars['Float'];
     category: TaxCategory;
     zone: Zone;
     customerGroup?: Maybe<CustomerGroup>;

+ 141 - 0
packages/core/e2e/tax-rate.e2e-spec.ts

@@ -0,0 +1,141 @@
+/* tslint:disable:no-non-null-assertion */
+import { pick } from '@vendure/common/lib/pick';
+import { createTestEnvironment } from '@vendure/testing';
+import gql from 'graphql-tag';
+import path from 'path';
+
+import { initialData } from '../../../e2e-common/e2e-initial-data';
+import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
+
+import { CreateTaxRate, GetTaxRate, GetTaxRates, UpdateTaxRate } from './graphql/generated-e2e-admin-types';
+
+describe('TaxRate resolver', () => {
+    const { server, adminClient, shopClient } = createTestEnvironment(testConfig);
+
+    beforeAll(async () => {
+        await server.init({
+            dataDir: path.join(__dirname, '__data__'),
+            initialData,
+            productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
+            customerCount: 2,
+        });
+        await adminClient.asSuperAdmin();
+    }, TEST_SETUP_TIMEOUT_MS);
+
+    afterAll(async () => {
+        await server.destroy();
+    });
+
+    it('taxRates list', async () => {
+        const { taxRates } = await adminClient.query<GetTaxRates.Query>(GET_TAX_RATES_LIST);
+
+        expect(taxRates.totalItems).toBe(15);
+    });
+
+    it('taxRate', async () => {
+        const { taxRate } = await adminClient.query<GetTaxRate.Query, GetTaxRate.Variables>(GET_TAX_RATE, {
+            id: 'T_1',
+        });
+
+        expect(pick(taxRate!, ['id', 'name', 'enabled', 'value'])).toEqual({
+            id: 'T_1',
+            name: 'Standard Tax Oceania',
+            enabled: true,
+            value: 20,
+        });
+        expect(taxRate!.category.name).toBe('Standard Tax');
+        expect(taxRate!.zone.name).toBe('Oceania');
+    });
+
+    it('createTaxRate', async () => {
+        const { createTaxRate } = await adminClient.query<CreateTaxRate.Mutation, CreateTaxRate.Variables>(
+            CREATE_TAX_RATE,
+            {
+                input: {
+                    name: 'My Tax Rate',
+                    categoryId: 'T_1',
+                    zoneId: 'T_1',
+                    enabled: true,
+                    value: 17.5,
+                },
+            },
+        );
+
+        expect(createTaxRate.name).toBe('My Tax Rate');
+        expect(createTaxRate.value).toBe(17.5);
+    });
+
+    it('updateTaxRate', async () => {
+        const { updateTaxRate } = await adminClient.query<UpdateTaxRate.Mutation, UpdateTaxRate.Variables>(
+            UPDATE_TAX_RATE,
+            {
+                input: {
+                    id: 'T_1',
+                    value: 17.5,
+                },
+            },
+        );
+
+        expect(updateTaxRate.value).toBe(17.5);
+    });
+});
+
+export const TAX_RATE_FRAGMENT = gql`
+    fragment TaxRate on TaxRate {
+        id
+        name
+        value
+        enabled
+        zone {
+            id
+            name
+        }
+        category {
+            id
+            name
+        }
+        customerGroup {
+            id
+            name
+        }
+    }
+`;
+
+export const GET_TAX_RATES_LIST = gql`
+    query GetTaxRates {
+        taxRates {
+            items {
+                ...TaxRate
+            }
+            totalItems
+        }
+    }
+    ${TAX_RATE_FRAGMENT}
+`;
+
+export const GET_TAX_RATE = gql`
+    query GetTaxRate($id: ID!) {
+        taxRate(id: $id) {
+            ...TaxRate
+        }
+    }
+    ${TAX_RATE_FRAGMENT}
+`;
+
+export const CREATE_TAX_RATE = gql`
+    mutation CreateTaxRate($input: CreateTaxRateInput!) {
+        createTaxRate(input: $input) {
+            ...TaxRate
+        }
+    }
+    ${TAX_RATE_FRAGMENT}
+`;
+
+export const UPDATE_TAX_RATE = gql`
+    mutation UpdateTaxRate($input: UpdateTaxRateInput!) {
+        updateTaxRate(input: $input) {
+            ...TaxRate
+        }
+    }
+    ${TAX_RATE_FRAGMENT}
+`;

+ 2 - 2
packages/core/src/api/schema/admin-api/tax-rate.api.graphql

@@ -16,7 +16,7 @@ input TaxRateListOptions
 input CreateTaxRateInput {
     name: String!
     enabled: Boolean!
-    value: Int!
+    value: Float!
     categoryId: ID!
     zoneId: ID!
     customerGroupId: ID
@@ -25,7 +25,7 @@ input CreateTaxRateInput {
 input UpdateTaxRateInput {
     id: ID!
     name: String
-    value: Int
+    value: Float
     enabled: Boolean
     categoryId: ID
     zoneId: ID

+ 1 - 1
packages/core/src/api/schema/type/tax-rate.type.graphql

@@ -4,7 +4,7 @@ type TaxRate implements Node {
     updatedAt: DateTime!
     name: String!
     enabled: Boolean!
-    value: Int!
+    value: Float!
     category: TaxCategory!
     zone: Zone!
     customerGroup: CustomerGroup

+ 1 - 1
packages/core/src/entity/tax-rate/tax-rate.entity.ts

@@ -30,7 +30,7 @@ export class TaxRate extends AdjustmentSource {
 
     @Column() enabled: boolean;
 
-    @Column() value: number;
+    @Column({ type: 'decimal', precision: 5, scale: 2 }) value: number;
 
     @ManyToOne(type => TaxCategory)
     category: TaxCategory;

+ 3 - 3
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts

@@ -561,7 +561,7 @@ export type CreateTaxCategoryInput = {
 export type CreateTaxRateInput = {
     name: Scalars['String'];
     enabled: Scalars['Boolean'];
-    value: Scalars['Int'];
+    value: Scalars['Float'];
     categoryId: Scalars['ID'];
     zoneId: Scalars['ID'];
     customerGroupId?: Maybe<Scalars['ID']>;
@@ -3146,7 +3146,7 @@ export type TaxRate = Node & {
     updatedAt: Scalars['DateTime'];
     name: Scalars['String'];
     enabled: Scalars['Boolean'];
-    value: Scalars['Int'];
+    value: Scalars['Float'];
     category: TaxCategory;
     zone: Zone;
     customerGroup?: Maybe<CustomerGroup>;
@@ -3384,7 +3384,7 @@ export type UpdateTaxCategoryInput = {
 export type UpdateTaxRateInput = {
     id: Scalars['ID'];
     name?: Maybe<Scalars['String']>;
-    value?: Maybe<Scalars['Int']>;
+    value?: Maybe<Scalars['Float']>;
     enabled?: Maybe<Scalars['Boolean']>;
     categoryId?: Maybe<Scalars['ID']>;
     zoneId?: Maybe<Scalars['ID']>;

File diff suppressed because it is too large
+ 0 - 0
schema-admin.json


File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff