diff --git a/LICENSE b/LICENSE index 39b4ac051a..b09b7e97d4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2020 Medusajs +Copyright (c) 2021 Medusajs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 57313056c0..86363dd6a9 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,6 @@ The Medusa repository is a mono-repository managed using Lerna. Lerna allows us ## Licensed -Licended under the [MIT License](https://github.com/medusajs/medusa/blob/master/LICENSE) +Licensed under the [MIT License](https://github.com/medusajs/medusa/blob/master/LICENSE) ## Thank you! diff --git a/integration-tests/api/__tests__/admin/discount.js b/integration-tests/api/__tests__/admin/discount.js index 575b1e0a0d..ee814d5335 100644 --- a/integration-tests/api/__tests__/admin/discount.js +++ b/integration-tests/api/__tests__/admin/discount.js @@ -104,6 +104,82 @@ describe("/admin/discounts", () => { }); }); + describe("testing for soft-deletion + uniqueness on discount codes", () => { + const manager = dbConnection.manager; + beforeEach(async () => { + try { + await adminSeeder(dbConnection); + await manager.insert(DiscountRule, { + id: "test-discount-rule", + description: "Test discount rule", + type: "percentage", + value: 10, + allocation: "total", + }); + await manager.insert(Discount, { + id: "test-discount", + code: "TESTING", + rule_id: "test-discount-rule", + }); + } catch (err) { + throw err; + } + }); + + afterEach(async () => { + await manager.query(`DELETE FROM "discount"`); + await manager.query(`DELETE FROM "discount_rule"`); + await manager.query(`DELETE FROM "user"`); + }); + + it("successfully creates discount with soft-deleted discount code", async () => { + const api = useApi(); + + // First we soft-delete the discount + await api + .delete("/admin/discounts/test-discount", { + headers: { + Authorization: "Bearer test_token", + }, + }) + .catch((err) => { + console.log(err); + }); + + // Lets try to create a discount with same code as deleted one + const response = await api + .post( + "/admin/discounts", + { + code: "TESTING", + rule: { + description: "test", + type: "percentage", + value: 10, + allocation: "total", + }, + usage_limit: 10, + }, + { + headers: { + Authorization: "Bearer test_token", + }, + } + ) + .catch((err) => { + console.log(err); + }); + + expect(response.status).toEqual(200); + expect(response.data.discount).toEqual( + expect.objectContaining({ + code: "HELLOWORLD", + usage_limit: 10, + }) + ); + }); + }); + describe("POST /admin/discounts/:discount_id/dynamic-codes", () => { beforeEach(async () => { const manager = dbConnection.manager; diff --git a/integration-tests/api/__tests__/admin/product.js b/integration-tests/api/__tests__/admin/product.js index 7a70eaf115..7b982d8c73 100644 --- a/integration-tests/api/__tests__/admin/product.js +++ b/integration-tests/api/__tests__/admin/product.js @@ -224,4 +224,208 @@ describe("/admin/products", () => { ); }); }); + describe("testing for soft-deletion + uniqueness on handles, collection and variant properties", () => { + beforeEach(async () => { + try { + await productSeeder(dbConnection); + await adminSeeder(dbConnection); + } catch (err) { + console.log(err); + throw err; + } + }); + + afterEach(async () => { + const manager = dbConnection.manager; + await manager.query(`DELETE FROM "product_option_value"`); + await manager.query(`DELETE FROM "product_option"`); + await manager.query(`DELETE FROM "image"`); + await manager.query(`DELETE FROM "money_amount"`); + await manager.query(`DELETE FROM "product_variant"`); + await manager.query(`DELETE FROM "product"`); + await manager.query(`DELETE FROM "product_collection"`); + await manager.query(`DELETE FROM "product_tag"`); + await manager.query(`DELETE FROM "product_type"`); + await manager.query( + `UPDATE "country" SET region_id=NULL WHERE iso_2 = 'us'` + ); + await manager.query(`DELETE FROM "region"`); + await manager.query(`DELETE FROM "user"`); + }); + + it("successfully deletes a product", async () => { + const api = useApi(); + + const response = await api + .delete("/admin/products/test-product", { + headers: { + Authorization: "Bearer test_token", + }, + }) + .catch((err) => { + console.log(err); + }); + + expect(response.status).toEqual(200); + + expect(response.data).toEqual( + expect.objectContaining({ + id: "test-product", + deleted: true, + }) + ); + }); + + it("successfully creates product with soft-deleted product handle", async () => { + const api = useApi(); + + // First we soft-delete the product + const response = await api + .delete("/admin/products/test-product", { + headers: { + Authorization: "Bearer test_token", + }, + }) + .catch((err) => { + console.log(err); + }); + + expect(response.status).toEqual(200); + expect(response.data.id).toEqual("test-product"); + + // Lets try to create a product with same handle as deleted one + const payload = { + title: "Test product", + handle: "test-product", + description: "test-product-description", + type: { value: "test-type" }, + images: ["test-image.png", "test-image-2.png"], + collection_id: "test-collection", + tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant", + inventory_quantity: 10, + prices: [{ currency_code: "usd", amount: 100 }], + options: [{ value: "large" }, { value: "green" }], + }, + ], + }; + + const res = await api.post("/admin/products", payload, { + headers: { + Authorization: "Bearer test_token", + }, + }); + + expect(res.status).toEqual(200); + expect(res.data.product.handle).toEqual("test-product"); + }); + + it("successfully deletes product collection", async () => { + const api = useApi(); + + // First we soft-delete the product collection + const response = await api + .delete("/admin/collections/test-collection", { + headers: { + Authorization: "Bearer test_token", + }, + }) + .catch((err) => { + console.log(err); + }); + + expect(response.status).toEqual(200); + expect(response.data.id).toEqual("test-collection"); + }); + + it("successfully creates soft-deleted product collection", async () => { + const api = useApi(); + + const response = await api + .delete("/admin/collections/test-collection", { + headers: { + Authorization: "Bearer test_token", + }, + }) + .catch((err) => { + console.log(err); + }); + + expect(response.status).toEqual(200); + expect(response.data.id).toEqual("test-collection"); + + // Lets try to create a product collection with same handle as deleted one + const payload = { + title: "Another test collection", + handle: "test-collection", + }; + + const res = await api.post("/admin/collections", payload, { + headers: { + Authorization: "Bearer test_token", + }, + }); + + expect(res.status).toEqual(200); + expect(res.data.collection.handle).toEqual("test-collection"); + }); + + it("successfully creates soft-deleted product variant", async () => { + const api = useApi(); + + const response = await api + .delete("/admin/products/test-product/variants/test-variant", { + headers: { + Authorization: "Bearer test_token", + }, + }) + .catch((err) => { + console.log(err); + }); + + expect(response.status).toEqual(200); + expect(response.data.variant_id).toEqual("test-variant"); + + // Lets try to create a product collection with same handle as deleted one + const payload = { + title: "Second variant", + sku: "test-sku", + ean: "test-ean", + upc: "test-upc", + barcode: "test-barcode", + prices: [ + { + currency_code: "usd", + amount: 100, + }, + ], + }; + + const res = await api.post( + "/admin/products/test-product/variants", + payload, + { + headers: { + Authorization: "Bearer test_token", + }, + } + ); + + expect(res.status).toEqual(200); + expect(res.data.product.variants).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + title: "Second variant", + sku: "test-sku", + ean: "test-ean", + upc: "test-upc", + barcode: "test-barcode", + }), + ]) + ); + }); + }); }); diff --git a/integration-tests/api/__tests__/store/customer.js b/integration-tests/api/__tests__/store/customer.js new file mode 100644 index 0000000000..2ed0f18ca4 --- /dev/null +++ b/integration-tests/api/__tests__/store/customer.js @@ -0,0 +1,230 @@ +const { dropDatabase } = require("pg-god"); +const path = require("path"); +const { Address, Customer } = require("@medusajs/medusa"); + +const setupServer = require("../../../helpers/setup-server"); +const { useApi } = require("../../../helpers/use-api"); +const { initDb } = require("../../../helpers/use-db"); + +const customerSeeder = require("../../helpers/customer-seeder"); + +jest.setTimeout(30000); + +describe("/store/customers", () => { + let medusaProcess; + let dbConnection; + + const doAfterEach = async (manager) => { + await manager.query(`DELETE FROM "customer"`); + await manager.query(`DELETE FROM "address"`); + }; + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..")); + dbConnection = await initDb({ cwd }); + medusaProcess = await setupServer({ cwd }); + }); + + afterAll(async () => { + dbConnection.close(); + await dropDatabase({ databaseName: "medusa-integration" }); + + medusaProcess.kill(); + }); + + describe("POST /store/customers", () => { + beforeEach(async () => { + const manager = dbConnection.manager; + + await manager.insert(Customer, { + id: "test_customer", + first_name: "John", + last_name: "Deere", + email: "john@deere.com", + has_account: true, + }); + }); + + afterEach(async () => { + const manager = dbConnection.manager; + await doAfterEach(manager); + }); + + it("creates a customer", async () => { + const api = useApi(); + + const response = await api.post("/store/customers", { + first_name: "James", + last_name: "Bond", + email: "james@bond.com", + password: "test", + }); + + expect(response.status).toEqual(200); + expect(response.data.customer).not.toHaveProperty("password_hash"); + }); + + it("responds 409 on duplicate", async () => { + const api = useApi(); + + const response = await api + .post("/store/customers", { + first_name: "James", + last_name: "Bond", + email: "john@deere.com", + password: "test", + }) + .catch((err) => err.response); + + expect(response.status).toEqual(409); + }); + }); + + describe("POST /store/customers/:id", () => { + beforeEach(async () => { + const manager = dbConnection.manager; + await manager.insert(Address, { + id: "addr_test", + first_name: "String", + last_name: "Stringson", + address_1: "String st", + city: "Stringville", + postal_code: "1236", + province: "ca", + country_code: "us", + }); + + await manager.insert(Customer, { + id: "test_customer", + first_name: "John", + last_name: "Deere", + email: "john@deere.com", + password_hash: + "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" + has_account: true, + }); + }); + + afterEach(async () => { + const manager = dbConnection.manager; + await doAfterEach(manager); + }); + + it("updates a customer", async () => { + const api = useApi(); + + const authResponse = await api.post("/store/auth", { + email: "john@deere.com", + password: "test", + }); + + const customerId = authResponse.data.customer.id; + const [authCookie] = authResponse.headers["set-cookie"][0].split(";"); + + const response = await api.post( + `/store/customers/${customerId}`, + { + password: "test", + metadata: { key: "value" }, + }, + { + headers: { + Cookie: authCookie, + }, + } + ); + + expect(response.status).toEqual(200); + expect(response.data.customer).not.toHaveProperty("password_hash"); + expect(response.data.customer).toEqual( + expect.objectContaining({ + metadata: { key: "value" }, + }) + ); + }); + + it("updates customer billing address", async () => { + const api = useApi(); + + const authResponse = await api.post("/store/auth", { + email: "john@deere.com", + password: "test", + }); + + const customerId = authResponse.data.customer.id; + const [authCookie] = authResponse.headers["set-cookie"][0].split(";"); + + const response = await api.post( + `/store/customers/${customerId}`, + { + billing_address: { + first_name: "test", + last_name: "testson", + address_1: "Test st", + city: "Testion", + postal_code: "1235", + province: "ca", + country_code: "us", + }, + }, + { + headers: { + Cookie: authCookie, + }, + } + ); + + expect(response.status).toEqual(200); + expect(response.data.customer).not.toHaveProperty("password_hash"); + expect(response.data.customer.billing_address).toEqual( + expect.objectContaining({ + first_name: "test", + last_name: "testson", + address_1: "Test st", + city: "Testion", + postal_code: "1235", + province: "ca", + country_code: "us", + }) + ); + }); + + it("updates customer billing address with string", async () => { + const api = useApi(); + + const authResponse = await api.post("/store/auth", { + email: "john@deere.com", + password: "test", + }); + + const customerId = authResponse.data.customer.id; + const [authCookie] = authResponse.headers["set-cookie"][0].split(";"); + + const response = await api.post( + `/store/customers/${customerId}`, + { + billing_address: "addr_test", + }, + { + headers: { + Cookie: authCookie, + }, + } + ); + + expect(response.status).toEqual(200); + expect(response.data.customer).not.toHaveProperty("password_hash"); + expect(response.data.customer.billing_address).toEqual( + expect.objectContaining({ + first_name: "String", + last_name: "Stringson", + address_1: "String st", + city: "Stringville", + postal_code: "1236", + province: "ca", + country_code: "us", + }) + ); + }); + }); +}); diff --git a/integration-tests/api/helpers/product-seeder.js b/integration-tests/api/helpers/product-seeder.js index 79e6f4eb97..77fd31a034 100644 --- a/integration-tests/api/helpers/product-seeder.js +++ b/integration-tests/api/helpers/product-seeder.js @@ -18,6 +18,7 @@ module.exports = async (connection, data = {}) => { const coll = manager.create(ProductCollection, { id: "test-collection", + handle: "test-collection", title: "Test collection", }); @@ -53,6 +54,7 @@ module.exports = async (connection, data = {}) => { const p = manager.create(Product, { id: "test-product", + handle: "test-product", title: "Test product", profile_id: defaultProfile.id, description: "test-product-description", @@ -73,6 +75,10 @@ module.exports = async (connection, data = {}) => { id: "test-variant", inventory_quantity: 10, title: "Test variant", + sku: "test-sku", + ean: "test-ean", + upc: "test-upc", + barcode: "test-barcode", product_id: "test-product", prices: [{ id: "test-price", currency_code: "usd", amount: 100 }], options: [{ id: "test-variant-option", value: "Default variant" }], diff --git a/integration-tests/api/package.json b/integration-tests/api/package.json index c497e7b1ac..ce709d3978 100644 --- a/integration-tests/api/package.json +++ b/integration-tests/api/package.json @@ -8,15 +8,15 @@ "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { - "@medusajs/medusa": "1.1.23-dev-1623081876060", - "medusa-interfaces": "1.1.10-dev-1623081876060", + "@medusajs/medusa": "1.1.29-dev-1626162503472", + "medusa-interfaces": "1.1.17-dev-1626162503472", "typeorm": "^0.2.31" }, "devDependencies": { "@babel/cli": "^7.12.10", "@babel/core": "^7.12.10", "@babel/node": "^7.12.10", - "babel-preset-medusa-package": "1.1.3-dev-1623168481467", + "babel-preset-medusa-package": "1.1.10-dev-1626162503472", "jest": "^26.6.3" } } diff --git a/integration-tests/api/yarn.lock b/integration-tests/api/yarn.lock index 24a83c4c80..a99f579dee 100644 --- a/integration-tests/api/yarn.lock +++ b/integration-tests/api/yarn.lock @@ -1215,10 +1215,10 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@medusajs/medusa@1.1.23-dev-1623081876060": - version "1.1.23" - resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.1.23.tgz#420eae69b20bc3b5a4c8f81825ba46252a1f1c92" - integrity sha512-1n9unNwt1jQV0SGd7053BIIb5P/PzPhX3fFgpwT4OzVbMOewnF6CLNMDaiQ1gI53JbkFY1rbjUPsRZk+9jVrYg== +"@medusajs/medusa@1.1.29-dev-1626162503472": + version "1.1.29-dev-1626162503472" + resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.1.29-dev-1626162503472.tgz#973ec19d02a66864c8cc11ac3e045cda2a82215d" + integrity sha512-8JDjTzOh056panREJIpN6uh2nwhauKqJHeGopG0Kdaw7sxOS3GJMBIfkwmUeNjju+cnpzj0nKlnJ56UgNMZSvA== dependencies: "@hapi/joi" "^16.1.8" "@types/lodash" "^4.14.168" @@ -1239,8 +1239,8 @@ joi "^17.3.0" joi-objectid "^3.0.1" jsonwebtoken "^8.5.1" - medusa-core-utils "^1.1.9" - medusa-test-utils "^1.1.12" + medusa-core-utils "1.1.16-dev-1626162503472" + medusa-test-utils "1.1.19-dev-1626162503472" morgan "^1.9.1" multer "^1.4.2" passport "^0.4.0" @@ -1696,10 +1696,10 @@ babel-preset-jest@^26.6.2: babel-plugin-jest-hoist "^26.6.2" babel-preset-current-node-syntax "^1.0.0" -babel-preset-medusa-package@1.1.3-dev-1623168481467: - version "1.1.3-dev-1623168481467" - resolved "http://localhost:4873/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.3-dev-1623168481467.tgz#ae9167644267c52c1016c4695294d81059dfc2ff" - integrity sha512-QombHh4IHvYll+DwUgeL93+uNCcFCSW6/rv/rrmcS4MMB+TeZ5iQrK+i1Gf/ns10v1WH2q0+VdExu9GDrdwU3Q== +babel-preset-medusa-package@1.1.10-dev-1626162503472: + version "1.1.10-dev-1626162503472" + resolved "http://localhost:4873/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.10-dev-1626162503472.tgz#65bba4e47361d9298b894fe9c08122fd60e0fd54" + integrity sha512-kQIZbFKnCnngCxxnPI3Ri+TC+6sadQOPgPGSMxd2X3yLm/W9RU+BLxRCLPEQcvvt6jeUA8dil8n0NUSl51cQnQ== dependencies: "@babel/plugin-proposal-class-properties" "^7.12.1" "@babel/plugin-proposal-decorators" "^7.12.1" @@ -4150,28 +4150,28 @@ media-typer@0.3.0: resolved "http://localhost:4873/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -medusa-core-utils@^1.1.9: - version "1.1.9" - resolved "http://localhost:4873/medusa-core-utils/-/medusa-core-utils-1.1.9.tgz#7b93c72d9c318ff4ab971381401158eee7d3edd9" - integrity sha512-XBxwpCQT82gi/S92Bc0qfCSYyD5Hj+zstUbyOCKGp7nhwFPvYwJ0hp6NPKDSwHZ1uPEmb4rdHcW2qyf1bM4L1Q== +medusa-core-utils@1.1.16-dev-1626162503472: + version "1.1.16-dev-1626162503472" + resolved "http://localhost:4873/medusa-core-utils/-/medusa-core-utils-1.1.16-dev-1626162503472.tgz#f72029605508928f689df3e35969db8c90be9cfd" + integrity sha512-AsI8UNF2VaJIUppJHjipsQnO6o7O/HNjIx5yPamriZRHatevZpWnRAD3aCejz25gaPvUQHWZ66b+UunPz1YKmQ== dependencies: joi "^17.3.0" joi-objectid "^3.0.1" -medusa-interfaces@1.1.10-dev-1623081876060: - version "1.1.10" - resolved "http://localhost:4873/medusa-interfaces/-/medusa-interfaces-1.1.10.tgz#e81b885e11d6c2f05db8d2971edf30b8f8e7ddaa" - integrity sha512-FJSpX3CE5jx2mYqRARFSp5C6x5Hq+MEZ6p2UikuWnm40qjGsbHNl4naZFdBS1u/vSnXq+607oHuZnCNnpRDrPQ== +medusa-interfaces@1.1.17-dev-1626162503472: + version "1.1.17-dev-1626162503472" + resolved "http://localhost:4873/medusa-interfaces/-/medusa-interfaces-1.1.17-dev-1626162503472.tgz#5cb72816c241a0074fbdbc64c2dfb0bedc073c03" + integrity sha512-aQcK39oMGBvb27aIHW3ko5sRdP2GRUAllXzrsTy3aQbUYzZxqnq3FHRlTjmBUWa9zbzwvfu3JLwdCEgZTfgr6Q== dependencies: - medusa-core-utils "^1.1.9" + medusa-core-utils "1.1.16-dev-1626162503472" -medusa-test-utils@^1.1.12: - version "1.1.12" - resolved "http://localhost:4873/medusa-test-utils/-/medusa-test-utils-1.1.12.tgz#1a731a3bd0c7266105b75d88dce7c09657432002" - integrity sha512-h/xpN0Mq1DRS7pDzEDjHfkZtpw1iLDKnytwBd12Lzs9RsWpQOJArfqSocAqdDrIO7GbxykhkFDCdl3Yi/q59gw== +medusa-test-utils@1.1.19-dev-1626162503472: + version "1.1.19-dev-1626162503472" + resolved "http://localhost:4873/medusa-test-utils/-/medusa-test-utils-1.1.19-dev-1626162503472.tgz#0a112fa9d5df2a2ce913312bb0527049ceb23e48" + integrity sha512-e9VsUYh0B1dzrmg0OAyHAMaEV+Ifrf2yqWl2ecGkwCX75whLgjfDxjR6dXlkahy+oL1Uqm3eGWZol04ZjIol7A== dependencies: "@babel/plugin-transform-classes" "^7.9.5" - medusa-core-utils "^1.1.9" + medusa-core-utils "1.1.16-dev-1626162503472" randomatic "^3.1.1" merge-descriptors@1.0.1: diff --git a/packages/babel-preset-medusa-package/CHANGELOG.md b/packages/babel-preset-medusa-package/CHANGELOG.md index 673bf24c69..e9ed17594b 100644 --- a/packages/babel-preset-medusa-package/CHANGELOG.md +++ b/packages/babel-preset-medusa-package/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/medusajs/medusa/compare/babel-preset-medusa-package@1.1.10...babel-preset-medusa-package@1.1.11) (2021-07-15) + +**Note:** Version bump only for package babel-preset-medusa-package + + + + + ## [1.1.10](https://github.com/medusajs/medusa/compare/babel-preset-medusa-package@1.1.9...babel-preset-medusa-package@1.1.10) (2021-07-02) **Note:** Version bump only for package babel-preset-medusa-package diff --git a/packages/babel-preset-medusa-package/package.json b/packages/babel-preset-medusa-package/package.json index 251937c607..b156c90fcb 100644 --- a/packages/babel-preset-medusa-package/package.json +++ b/packages/babel-preset-medusa-package/package.json @@ -1,6 +1,6 @@ { "name": "babel-preset-medusa-package", - "version": "1.1.10", + "version": "1.1.11", "author": "Sebastian Rindom ", "repository": { "type": "git", diff --git a/packages/medusa-cli/CHANGELOG.md b/packages/medusa-cli/CHANGELOG.md index b264617489..7d369de170 100644 --- a/packages/medusa-cli/CHANGELOG.md +++ b/packages/medusa-cli/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.12](https://github.com/medusajs/medusa/compare/@medusajs/medusa-cli@1.1.11...@medusajs/medusa-cli@1.1.12) (2021-07-15) + +**Note:** Version bump only for package @medusajs/medusa-cli + + + + + ## [1.1.11](https://github.com/medusajs/medusa/compare/@medusajs/medusa-cli@1.1.10...@medusajs/medusa-cli@1.1.11) (2021-07-02) **Note:** Version bump only for package @medusajs/medusa-cli diff --git a/packages/medusa-cli/package.json b/packages/medusa-cli/package.json index f261877f83..eadb585e55 100644 --- a/packages/medusa-cli/package.json +++ b/packages/medusa-cli/package.json @@ -1,6 +1,6 @@ { "name": "@medusajs/medusa-cli", - "version": "1.1.11", + "version": "1.1.12", "description": "Command Line interface for Medusa Commerce", "main": "dist/index.js", "bin": { diff --git a/packages/medusa-core-utils/CHANGELOG.md b/packages/medusa-core-utils/CHANGELOG.md index d8452e3649..3134174791 100644 --- a/packages/medusa-core-utils/CHANGELOG.md +++ b/packages/medusa-core-utils/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.17](https://github.com/medusajs/medusa/compare/medusa-core-utils@1.1.16...medusa-core-utils@1.1.17) (2021-07-15) + + +### Bug Fixes + +* better store/customer support ([6342e68](https://github.com/medusajs/medusa/commit/6342e68d069636e5eb4877c7ebf7aac952b5e363)) + + + + + ## [1.1.16](https://github.com/medusajs/medusa/compare/medusa-core-utils@1.1.15...medusa-core-utils@1.1.16) (2021-07-02) **Note:** Version bump only for package medusa-core-utils diff --git a/packages/medusa-core-utils/package.json b/packages/medusa-core-utils/package.json index a844a671ba..6f61def77a 100644 --- a/packages/medusa-core-utils/package.json +++ b/packages/medusa-core-utils/package.json @@ -1,6 +1,6 @@ { "name": "medusa-core-utils", - "version": "1.1.16", + "version": "1.1.17", "description": "Core utils for Medusa", "main": "dist/index.js", "repository": { diff --git a/packages/medusa-core-utils/src/errors.js b/packages/medusa-core-utils/src/errors.js index eae11818fc..88250a081b 100644 --- a/packages/medusa-core-utils/src/errors.js +++ b/packages/medusa-core-utils/src/errors.js @@ -5,10 +5,11 @@ export const MedusaErrorTypes = { /** Errors stemming from the database */ DB_ERROR: "database_error", + DUPLICATE_ERROR: "duplicate_error", INVALID_ARGUMENT: "invalid_argument", INVALID_DATA: "invalid_data", NOT_FOUND: "not_found", - NOT_ALLOWED: "not_allowed" + NOT_ALLOWED: "not_allowed", } /** diff --git a/packages/medusa-core-utils/yarn.lock b/packages/medusa-core-utils/yarn.lock index 037f32afe4..61a5d8896f 100644 --- a/packages/medusa-core-utils/yarn.lock +++ b/packages/medusa-core-utils/yarn.lock @@ -3740,12 +3740,7 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -lodash@^4.17.19: +lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== diff --git a/packages/medusa-dev-cli/CHANGELOG.md b/packages/medusa-dev-cli/CHANGELOG.md index e0e07ebf6f..344b0cbfe4 100644 --- a/packages/medusa-dev-cli/CHANGELOG.md +++ b/packages/medusa-dev-cli/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.0.16](https://github.com/medusajs/medusa/compare/medusa-dev-cli@0.0.15...medusa-dev-cli@0.0.16) (2021-07-15) + +**Note:** Version bump only for package medusa-dev-cli + + + + + ## [0.0.15](https://github.com/medusajs/medusa/compare/medusa-dev-cli@0.0.14...medusa-dev-cli@0.0.15) (2021-07-02) **Note:** Version bump only for package medusa-dev-cli diff --git a/packages/medusa-dev-cli/package.json b/packages/medusa-dev-cli/package.json index 986627f3a7..a92882e3b4 100644 --- a/packages/medusa-dev-cli/package.json +++ b/packages/medusa-dev-cli/package.json @@ -1,7 +1,7 @@ { "name": "medusa-dev-cli", "description": "CLI helpers for contributors working on Medusa", - "version": "0.0.15", + "version": "0.0.16", "author": "Sebastian Rindom ", "bin": { "medusa-dev": "./dist/index.js" @@ -24,7 +24,7 @@ "devDependencies": { "@babel/cli": "^7.12.1", "@babel/core": "^7.12.3", - "babel-preset-medusa-package": "^1.1.10", + "babel-preset-medusa-package": "^1.1.11", "cross-env": "^7.0.3" }, "homepage": "https://github.com/medusajs/medusa/tree/master/packages/medusa-dev-cli#readme", diff --git a/packages/medusa-file-spaces/CHANGELOG.md b/packages/medusa-file-spaces/CHANGELOG.md index 6c5bbe081b..bce27cb5cf 100644 --- a/packages/medusa-file-spaces/CHANGELOG.md +++ b/packages/medusa-file-spaces/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-file-spaces@1.1.19...medusa-file-spaces@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-file-spaces + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-file-spaces@1.1.18...medusa-file-spaces@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-file-spaces diff --git a/packages/medusa-file-spaces/package.json b/packages/medusa-file-spaces/package.json index a53240d1e5..46fc8cf672 100644 --- a/packages/medusa-file-spaces/package.json +++ b/packages/medusa-file-spaces/package.json @@ -1,6 +1,6 @@ { "name": "medusa-file-spaces", - "version": "1.1.19", + "version": "1.1.20", "description": "Digital Ocean Spaces file connector for Medusa", "main": "index.js", "repository": { @@ -40,8 +40,8 @@ "aws-sdk": "^2.710.0", "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19", + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20", "stripe": "^8.50.0" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-fulfillment-manual/CHANGELOG.md b/packages/medusa-fulfillment-manual/CHANGELOG.md index 2b6eba9bab..60831572ee 100644 --- a/packages/medusa-fulfillment-manual/CHANGELOG.md +++ b/packages/medusa-fulfillment-manual/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.17](https://github.com/medusajs/medusa/compare/medusa-fulfillment-manual@1.1.16...medusa-fulfillment-manual@1.1.17) (2021-07-15) + +**Note:** Version bump only for package medusa-fulfillment-manual + + + + + ## [1.1.16](https://github.com/medusajs/medusa/compare/medusa-fulfillment-manual@1.1.15...medusa-fulfillment-manual@1.1.16) (2021-07-02) **Note:** Version bump only for package medusa-fulfillment-manual diff --git a/packages/medusa-fulfillment-manual/package.json b/packages/medusa-fulfillment-manual/package.json index d5aa3bfd31..e85b244806 100644 --- a/packages/medusa-fulfillment-manual/package.json +++ b/packages/medusa-fulfillment-manual/package.json @@ -1,6 +1,6 @@ { "name": "medusa-fulfillment-manual", - "version": "1.1.16", + "version": "1.1.17", "description": "A manual fulfillment provider for Medusa", "main": "index.js", "repository": { @@ -36,7 +36,7 @@ "@babel/plugin-transform-instanceof": "^7.8.3", "@babel/runtime": "^7.7.6", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16" + "medusa-core-utils": "^1.1.17" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-fulfillment-webshipper/CHANGELOG.md b/packages/medusa-fulfillment-webshipper/CHANGELOG.md index 6b19bdad70..772c9d0a93 100644 --- a/packages/medusa-fulfillment-webshipper/CHANGELOG.md +++ b/packages/medusa-fulfillment-webshipper/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.21](https://github.com/medusajs/medusa/compare/medusa-fulfillment-webshipper@1.1.20...medusa-fulfillment-webshipper@1.1.21) (2021-07-15) + +**Note:** Version bump only for package medusa-fulfillment-webshipper + + + + + ## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-fulfillment-webshipper@1.1.19...medusa-fulfillment-webshipper@1.1.20) (2021-07-02) **Note:** Version bump only for package medusa-fulfillment-webshipper diff --git a/packages/medusa-fulfillment-webshipper/package.json b/packages/medusa-fulfillment-webshipper/package.json index afb8eaaf74..094c5f6f3b 100644 --- a/packages/medusa-fulfillment-webshipper/package.json +++ b/packages/medusa-fulfillment-webshipper/package.json @@ -1,6 +1,6 @@ { "name": "medusa-fulfillment-webshipper", - "version": "1.1.20", + "version": "1.1.21", "description": "Webshipper Fulfillment provider for Medusa", "main": "index.js", "repository": { @@ -37,7 +37,7 @@ "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16" + "medusa-core-utils": "^1.1.17" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-interfaces/CHANGELOG.md b/packages/medusa-interfaces/CHANGELOG.md index 9d69a3221b..c1ee772007 100644 --- a/packages/medusa-interfaces/CHANGELOG.md +++ b/packages/medusa-interfaces/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.18](https://github.com/medusajs/medusa/compare/medusa-interfaces@1.1.17...medusa-interfaces@1.1.18) (2021-07-15) + +**Note:** Version bump only for package medusa-interfaces + + + + + ## [1.1.17](https://github.com/medusajs/medusa/compare/medusa-interfaces@1.1.16...medusa-interfaces@1.1.17) (2021-07-02) **Note:** Version bump only for package medusa-interfaces diff --git a/packages/medusa-interfaces/package.json b/packages/medusa-interfaces/package.json index f4542bf2a2..130c58de55 100644 --- a/packages/medusa-interfaces/package.json +++ b/packages/medusa-interfaces/package.json @@ -1,6 +1,6 @@ { "name": "medusa-interfaces", - "version": "1.1.17", + "version": "1.1.18", "description": "Core interfaces for Medusa", "main": "dist/index.js", "repository": { @@ -35,7 +35,7 @@ "typeorm": "0.x" }, "dependencies": { - "medusa-core-utils": "^1.1.16" + "medusa-core-utils": "^1.1.17" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-payment-adyen/CHANGELOG.md b/packages/medusa-payment-adyen/CHANGELOG.md index 98e257730e..e7c86db71a 100644 --- a/packages/medusa-payment-adyen/CHANGELOG.md +++ b/packages/medusa-payment-adyen/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.22](https://github.com/medusajs/medusa/compare/medusa-payment-adyen@1.1.21...medusa-payment-adyen@1.1.22) (2021-07-15) + +**Note:** Version bump only for package medusa-payment-adyen + + + + + ## [1.1.21](https://github.com/medusajs/medusa/compare/medusa-payment-adyen@1.1.20...medusa-payment-adyen@1.1.21) (2021-07-02) **Note:** Version bump only for package medusa-payment-adyen diff --git a/packages/medusa-payment-adyen/package.json b/packages/medusa-payment-adyen/package.json index efc9123d9a..ec9dcf9cbc 100644 --- a/packages/medusa-payment-adyen/package.json +++ b/packages/medusa-payment-adyen/package.json @@ -1,6 +1,6 @@ { "name": "medusa-payment-adyen", - "version": "1.1.21", + "version": "1.1.22", "description": "Adyen Payment provider for Medusa Commerce", "main": "index.js", "repository": { @@ -24,7 +24,7 @@ "cross-env": "^7.0.2", "eslint": "^6.8.0", "jest": "^25.5.2", - "medusa-test-utils": "^1.1.19" + "medusa-test-utils": "^1.1.20" }, "scripts": { "build": "babel src -d .", @@ -42,7 +42,7 @@ "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16" + "medusa-core-utils": "^1.1.17" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-payment-klarna/CHANGELOG.md b/packages/medusa-payment-klarna/CHANGELOG.md index e5aa424034..d718fe01ad 100644 --- a/packages/medusa-payment-klarna/CHANGELOG.md +++ b/packages/medusa-payment-klarna/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.22](https://github.com/medusajs/medusa/compare/medusa-payment-klarna@1.1.21...medusa-payment-klarna@1.1.22) (2021-07-15) + +**Note:** Version bump only for package medusa-payment-klarna + + + + + ## [1.1.21](https://github.com/medusajs/medusa/compare/medusa-payment-klarna@1.1.20...medusa-payment-klarna@1.1.21) (2021-07-02) **Note:** Version bump only for package medusa-payment-klarna diff --git a/packages/medusa-payment-klarna/package.json b/packages/medusa-payment-klarna/package.json index 147d599f97..2c1b8945b6 100644 --- a/packages/medusa-payment-klarna/package.json +++ b/packages/medusa-payment-klarna/package.json @@ -1,6 +1,6 @@ { "name": "medusa-payment-klarna", - "version": "1.1.21", + "version": "1.1.22", "description": "Klarna Payment provider for Medusa Commerce", "main": "index.js", "repository": { @@ -40,8 +40,8 @@ "axios": "^0.21.0", "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19" + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-payment-paypal/CHANGELOG.md b/packages/medusa-payment-paypal/CHANGELOG.md index b8ef654bfe..e49fde2105 100644 --- a/packages/medusa-payment-paypal/CHANGELOG.md +++ b/packages/medusa-payment-paypal/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.21](https://github.com/medusajs/medusa/compare/medusa-payment-paypal@1.0.20...medusa-payment-paypal@1.0.21) (2021-07-15) + + +### Bug Fixes + +* paypal order ([1f6ee0f](https://github.com/medusajs/medusa/commit/1f6ee0fc00024c25d6628e6531097f93f54f8a1b)) +* support for hook completion of swap carts ([fca29cc](https://github.com/medusajs/medusa/commit/fca29cc5cc0d6f20d01fada7445d32da85291cd8)) + + + + + ## [1.0.20](https://github.com/medusajs/medusa/compare/medusa-payment-paypal@1.0.19...medusa-payment-paypal@1.0.20) (2021-07-02) **Note:** Version bump only for package medusa-payment-paypal diff --git a/packages/medusa-payment-paypal/package.json b/packages/medusa-payment-paypal/package.json index 7044a2ebec..b73d082daa 100644 --- a/packages/medusa-payment-paypal/package.json +++ b/packages/medusa-payment-paypal/package.json @@ -1,6 +1,6 @@ { "name": "medusa-payment-paypal", - "version": "1.0.20", + "version": "1.0.21", "description": "Paypal Payment provider for Meduas Commerce", "main": "index.js", "repository": { @@ -26,8 +26,8 @@ "cross-env": "^5.2.1", "eslint": "^6.8.0", "jest": "^25.5.2", - "medusa-interfaces": "^1.1.17", - "medusa-test-utils": "^1.1.19" + "medusa-interfaces": "^1.1.18", + "medusa-test-utils": "^1.1.20" }, "scripts": { "build": "babel src -d . --ignore **/__tests__,**/__mocks__", @@ -42,7 +42,7 @@ "@paypal/checkout-server-sdk": "^1.0.2", "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16" + "medusa-core-utils": "^1.1.17" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-payment-paypal/src/api/routes/hooks/paypal.js b/packages/medusa-payment-paypal/src/api/routes/hooks/paypal.js index 03fa6d3276..8803ccb6b5 100644 --- a/packages/medusa-payment-paypal/src/api/routes/hooks/paypal.js +++ b/packages/medusa-payment-paypal/src/api/routes/hooks/paypal.js @@ -22,7 +22,8 @@ export default async (req, res) => { } try { - const authId = req.body.resource.id + const body = req.body + const authId = body.resource.id const auth = await paypalService.retrieveAuthorization(authId) const order = await paypalService.retrieveOrderFromAuth(auth) @@ -37,18 +38,44 @@ export default async (req, res) => { const manager = req.scope.resolve("manager") const cartService = req.scope.resolve("cartService") + const swapService = req.scope.resolve("swapService") const orderService = req.scope.resolve("orderService") await manager.transaction(async (m) => { - const order = await orderService - .withTransaction(m) - .retrieveByCartId(cartId) - .catch((_) => undefined) + const cart = await cartService.withTransaction(m).retrieve(cartId) - if (!order) { - await cartService.withTransaction(m).setPaymentSession(cartId, "paypal") - await cartService.withTransaction(m).authorizePayment(cartId) - await orderService.withTransaction(m).createFromCart(cartId) + switch (cart.type) { + case "swap": { + const swap = await swapService + .withTransaction(m) + .retrieveByCartId(cartId) + .catch((_) => undefined) + + if (swap && swap.confirmed_at === null) { + await cartService + .withTransaction(m) + .setPaymentSession(cartId, "paypal") + await cartService.withTransaction(m).authorizePayment(cartId) + await swapService.withTransaction(m).registerCartCompletion(swap.id) + } + break + } + + default: { + const order = await orderService + .withTransaction(m) + .retrieveByCartId(cartId) + .catch((_) => undefined) + + if (!order) { + await cartService + .withTransaction(m) + .setPaymentSession(cartId, "paypal") + await cartService.withTransaction(m).authorizePayment(cartId) + await orderService.withTransaction(m).createFromCart(cartId) + } + break + } } }) diff --git a/packages/medusa-payment-stripe/CHANGELOG.md b/packages/medusa-payment-stripe/CHANGELOG.md index 832146f4df..a2e23bf2c5 100644 --- a/packages/medusa-payment-stripe/CHANGELOG.md +++ b/packages/medusa-payment-stripe/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-payment-stripe@1.1.19...medusa-payment-stripe@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-payment-stripe + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-payment-stripe@1.1.18...medusa-payment-stripe@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-payment-stripe diff --git a/packages/medusa-payment-stripe/package.json b/packages/medusa-payment-stripe/package.json index 9a5968a387..5c94e32d5b 100644 --- a/packages/medusa-payment-stripe/package.json +++ b/packages/medusa-payment-stripe/package.json @@ -1,6 +1,6 @@ { "name": "medusa-payment-stripe", - "version": "1.1.19", + "version": "1.1.20", "description": "Stripe Payment provider for Meduas Commerce", "main": "index.js", "repository": { @@ -26,7 +26,7 @@ "cross-env": "^5.2.1", "eslint": "^6.8.0", "jest": "^25.5.2", - "medusa-test-utils": "^1.1.19" + "medusa-test-utils": "^1.1.20" }, "scripts": { "build": "babel src -d . --ignore **/__tests__", @@ -40,7 +40,7 @@ "dependencies": { "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", + "medusa-core-utils": "^1.1.17", "stripe": "^8.50.0" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-add-ons/CHANGELOG.md b/packages/medusa-plugin-add-ons/CHANGELOG.md index 865610ef13..ed4beb0123 100644 --- a/packages/medusa-plugin-add-ons/CHANGELOG.md +++ b/packages/medusa-plugin-add-ons/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.19...medusa-plugin-add-ons@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-add-ons + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-add-ons@1.1.18...medusa-plugin-add-ons@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-plugin-add-ons diff --git a/packages/medusa-plugin-add-ons/package.json b/packages/medusa-plugin-add-ons/package.json index 0305ff103f..e3f90dcd33 100644 --- a/packages/medusa-plugin-add-ons/package.json +++ b/packages/medusa-plugin-add-ons/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-add-ons", - "version": "1.1.19", + "version": "1.1.20", "description": "Add-on plugin for Medusa Commerce", "main": "index.js", "repository": { @@ -25,7 +25,7 @@ "cross-env": "^7.0.2", "eslint": "^6.8.0", "jest": "^25.5.2", - "medusa-test-utils": "^1.1.19" + "medusa-test-utils": "^1.1.20" }, "scripts": { "build": "babel src -d . --ignore **/__tests__", @@ -37,7 +37,7 @@ "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", + "medusa-core-utils": "^1.1.17", "redis": "^3.0.2" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-brightpearl/CHANGELOG.md b/packages/medusa-plugin-brightpearl/CHANGELOG.md index 832439b66b..2ec547751f 100644 --- a/packages/medusa-plugin-brightpearl/CHANGELOG.md +++ b/packages/medusa-plugin-brightpearl/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.25](https://github.com/medusajs/medusa/compare/medusa-plugin-brightpearl@1.1.24...medusa-plugin-brightpearl@1.1.25) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-brightpearl + + + + + ## [1.1.24](https://github.com/medusajs/medusa/compare/medusa-plugin-brightpearl@1.1.23...medusa-plugin-brightpearl@1.1.24) (2021-07-02) **Note:** Version bump only for package medusa-plugin-brightpearl diff --git a/packages/medusa-plugin-brightpearl/package.json b/packages/medusa-plugin-brightpearl/package.json index 1485e28a74..78a6a636aa 100644 --- a/packages/medusa-plugin-brightpearl/package.json +++ b/packages/medusa-plugin-brightpearl/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-brightpearl", - "version": "1.1.24", + "version": "1.1.25", "description": "Brightpearl plugin for Medusa Commerce", "main": "index.js", "repository": { @@ -27,7 +27,7 @@ "cross-env": "^7.0.2", "eslint": "^6.8.0", "jest": "^25.5.2", - "medusa-test-utils": "^1.1.19", + "medusa-test-utils": "^1.1.20", "prettier": "^2.0.5" }, "scripts": { @@ -43,7 +43,7 @@ "axios": "^0.19.2", "axios-rate-limit": "^1.2.1", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", + "medusa-core-utils": "^1.1.17", "randomatic": "^3.1.1" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-contentful/CHANGELOG.md b/packages/medusa-plugin-contentful/CHANGELOG.md index 7878205838..f1308df810 100644 --- a/packages/medusa-plugin-contentful/CHANGELOG.md +++ b/packages/medusa-plugin-contentful/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.22](https://github.com/medusajs/medusa/compare/medusa-plugin-contentful@1.1.21...medusa-plugin-contentful@1.1.22) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-contentful + + + + + ## [1.1.21](https://github.com/medusajs/medusa/compare/medusa-plugin-contentful@1.1.20...medusa-plugin-contentful@1.1.21) (2021-07-02) **Note:** Version bump only for package medusa-plugin-contentful diff --git a/packages/medusa-plugin-contentful/package.json b/packages/medusa-plugin-contentful/package.json index f39b71b945..264cf22ed4 100644 --- a/packages/medusa-plugin-contentful/package.json +++ b/packages/medusa-plugin-contentful/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-contentful", - "version": "1.1.21", + "version": "1.1.22", "description": "Contentful plugin for Medusa Commerce", "main": "index.js", "repository": { @@ -39,8 +39,8 @@ "body-parser": "^1.19.0", "contentful-management": "^5.27.1", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19", + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20", "redis": "^3.0.2" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-discount-generator/CHANGELOG.md b/packages/medusa-plugin-discount-generator/CHANGELOG.md index 29e51cd3a3..ccab5ad170 100644 --- a/packages/medusa-plugin-discount-generator/CHANGELOG.md +++ b/packages/medusa-plugin-discount-generator/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/medusajs/medusa/compare/medusa-plugin-discount-generator@1.1.10...medusa-plugin-discount-generator@1.1.11) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-discount-generator + + + + + ## [1.1.10](https://github.com/medusajs/medusa/compare/medusa-plugin-discount-generator@1.1.9...medusa-plugin-discount-generator@1.1.10) (2021-07-02) **Note:** Version bump only for package medusa-plugin-discount-generator diff --git a/packages/medusa-plugin-discount-generator/package.json b/packages/medusa-plugin-discount-generator/package.json index 51320536fb..3d518aaffc 100644 --- a/packages/medusa-plugin-discount-generator/package.json +++ b/packages/medusa-plugin-discount-generator/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-discount-generator", - "version": "1.1.10", + "version": "1.1.11", "main": "index.js", "license": "MIT", "author": "Sebastian Rindom", diff --git a/packages/medusa-plugin-economic/CHANGELOG.md b/packages/medusa-plugin-economic/CHANGELOG.md index ed6d4f9107..6ee52aae41 100644 --- a/packages/medusa-plugin-economic/CHANGELOG.md +++ b/packages/medusa-plugin-economic/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-economic@1.1.19...medusa-plugin-economic@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-economic + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-economic@1.1.18...medusa-plugin-economic@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-plugin-economic diff --git a/packages/medusa-plugin-economic/package-lock.json b/packages/medusa-plugin-economic/package-lock.json index 886dc85ccf..3db285ea1c 100644 --- a/packages/medusa-plugin-economic/package-lock.json +++ b/packages/medusa-plugin-economic/package-lock.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-economic", - "version": "1.1.19", + "version": "1.1.20", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/medusa-plugin-economic/package.json b/packages/medusa-plugin-economic/package.json index 3c952b42f7..c348ee0fbe 100644 --- a/packages/medusa-plugin-economic/package.json +++ b/packages/medusa-plugin-economic/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-economic", - "version": "1.1.19", + "version": "1.1.20", "description": "E-conomic financial reporting", "main": "index.js", "repository": { @@ -39,8 +39,8 @@ "axios": "^0.19.2", "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19", + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20", "moment": "^2.27.0" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-ip-lookup/CHANGELOG.md b/packages/medusa-plugin-ip-lookup/CHANGELOG.md index 20256fd444..934d43d4d2 100644 --- a/packages/medusa-plugin-ip-lookup/CHANGELOG.md +++ b/packages/medusa-plugin-ip-lookup/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.11](https://github.com/medusajs/medusa/compare/medusa-plugin-ip-lookup@1.1.10...medusa-plugin-ip-lookup@1.1.11) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-ip-lookup + + + + + ## [1.1.10](https://github.com/medusajs/medusa/compare/medusa-plugin-ip-lookup@1.1.9...medusa-plugin-ip-lookup@1.1.10) (2021-07-02) **Note:** Version bump only for package medusa-plugin-ip-lookup diff --git a/packages/medusa-plugin-ip-lookup/package.json b/packages/medusa-plugin-ip-lookup/package.json index e0a7edc1ea..faacecff73 100644 --- a/packages/medusa-plugin-ip-lookup/package.json +++ b/packages/medusa-plugin-ip-lookup/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-ip-lookup", - "version": "1.1.10", + "version": "1.1.11", "description": "IP lookup middleware for Medusa core", "main": "dist/index.js", "repository": { diff --git a/packages/medusa-plugin-mailchimp/CHANGELOG.md b/packages/medusa-plugin-mailchimp/CHANGELOG.md index 25ebe3de15..ff5aa73e5a 100644 --- a/packages/medusa-plugin-mailchimp/CHANGELOG.md +++ b/packages/medusa-plugin-mailchimp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-mailchimp@1.1.19...medusa-plugin-mailchimp@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-mailchimp + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-mailchimp@1.1.18...medusa-plugin-mailchimp@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-plugin-mailchimp diff --git a/packages/medusa-plugin-mailchimp/package.json b/packages/medusa-plugin-mailchimp/package.json index 925b357de7..964304af7e 100644 --- a/packages/medusa-plugin-mailchimp/package.json +++ b/packages/medusa-plugin-mailchimp/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-mailchimp", - "version": "1.1.19", + "version": "1.1.20", "description": "Mailchimp newsletter subscriptions", "main": "index.js", "repository": { @@ -40,8 +40,8 @@ "cors": "^2.8.5", "express": "^4.17.1", "mailchimp-api-v3": "^1.14.0", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19" + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-plugin-permissions/CHANGELOG.md b/packages/medusa-plugin-permissions/CHANGELOG.md index 0dc047b59d..bb7f3c9416 100644 --- a/packages/medusa-plugin-permissions/CHANGELOG.md +++ b/packages/medusa-plugin-permissions/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-permissions@1.1.19...medusa-plugin-permissions@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-permissions + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-permissions@1.1.18...medusa-plugin-permissions@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-plugin-permissions diff --git a/packages/medusa-plugin-permissions/package.json b/packages/medusa-plugin-permissions/package.json index 85c3548b2a..d64ca135eb 100644 --- a/packages/medusa-plugin-permissions/package.json +++ b/packages/medusa-plugin-permissions/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-permissions", - "version": "1.1.19", + "version": "1.1.20", "description": "Role permission for Medusa core", "main": "dist/index.js", "repository": { @@ -32,8 +32,8 @@ "medusa-interfaces": "1.x" }, "dependencies": { - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19", + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20", "mongoose": "^5.8.0" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-restock-notification/CHANGELOG.md b/packages/medusa-plugin-restock-notification/CHANGELOG.md index 93120d5e15..82abe14610 100644 --- a/packages/medusa-plugin-restock-notification/CHANGELOG.md +++ b/packages/medusa-plugin-restock-notification/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.0.13](https://github.com/medusajs/medusa/compare/medusa-plugin-restock-notification@0.0.12...medusa-plugin-restock-notification@0.0.13) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-restock-notification + + + + + ## [0.0.12](https://github.com/medusajs/medusa/compare/medusa-plugin-restock-notification@0.0.11...medusa-plugin-restock-notification@0.0.12) (2021-07-02) **Note:** Version bump only for package medusa-plugin-restock-notification diff --git a/packages/medusa-plugin-restock-notification/README.md b/packages/medusa-plugin-restock-notification/README.md index d63861df30..8e0f336a38 100644 --- a/packages/medusa-plugin-restock-notification/README.md +++ b/packages/medusa-plugin-restock-notification/README.md @@ -35,7 +35,7 @@ Body } ``` -The endpoint responds with `200 OK` on succesful signups. If a signup for an already in stock item is attempted the endpoint will have a 400 response code. +The endpoint responds with `200 OK` on successful signups. If a signup for an already in stock item is attempted the endpoint will have a 400 response code. ## Restock events diff --git a/packages/medusa-plugin-restock-notification/package.json b/packages/medusa-plugin-restock-notification/package.json index bc2345cfaf..64e3405934 100644 --- a/packages/medusa-plugin-restock-notification/package.json +++ b/packages/medusa-plugin-restock-notification/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-restock-notification", - "version": "0.0.12", + "version": "0.0.13", "main": "index.js", "repository": { "type": "git", @@ -14,11 +14,11 @@ "@babel/core": "^7.7.5", "@babel/plugin-transform-typescript": "^7.13.0", "@babel/preset-typescript": "^7.12.7", - "babel-preset-medusa-package": "^1.1.10", + "babel-preset-medusa-package": "^1.1.11", "cross-env": "^5.2.1", "eslint": "^6.8.0", "jest": "^25.5.2", - "medusa-test-utils": "^1.1.19", + "medusa-test-utils": "^1.1.20", "pg": "^8.5.1", "ulid": "^2.3.0" }, @@ -36,7 +36,7 @@ "body-parser": "^1.19.0", "cors": "^2.8.5", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16" + "medusa-core-utils": "^1.1.17" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-plugin-segment/CHANGELOG.md b/packages/medusa-plugin-segment/CHANGELOG.md index 8895d253e7..4c475c0a88 100644 --- a/packages/medusa-plugin-segment/CHANGELOG.md +++ b/packages/medusa-plugin-segment/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.23](https://github.com/medusajs/medusa/compare/medusa-plugin-segment@1.1.22...medusa-plugin-segment@1.1.23) (2021-07-15) + + +### Bug Fixes + +* sends return reasons to segment on Order Refunded event ([55ba9ba](https://github.com/medusajs/medusa/commit/55ba9bae05527d602d654f99d678b610c5ba7229)) + + + + + ## [1.1.22](https://github.com/medusajs/medusa/compare/medusa-plugin-segment@1.1.21...medusa-plugin-segment@1.1.22) (2021-07-02) **Note:** Version bump only for package medusa-plugin-segment diff --git a/packages/medusa-plugin-segment/package.json b/packages/medusa-plugin-segment/package.json index 2ed8131eb8..17c316d34f 100644 --- a/packages/medusa-plugin-segment/package.json +++ b/packages/medusa-plugin-segment/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-segment", - "version": "1.1.22", + "version": "1.1.23", "description": "Segment Analytics", "main": "index.js", "repository": { @@ -39,8 +39,8 @@ "axios": "^0.19.2", "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19" + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-plugin-segment/src/services/__tests__/segment.js b/packages/medusa-plugin-segment/src/services/__tests__/segment.js index 852820efc8..dff49cc3d0 100644 --- a/packages/medusa-plugin-segment/src/services/__tests__/segment.js +++ b/packages/medusa-plugin-segment/src/services/__tests__/segment.js @@ -134,6 +134,68 @@ describe("SegmentService", () => { }) }) + it("successfully adds return reason and note on buildOrder", async () => { + jest.clearAllMocks() + + const order = orderFactory() + order.items = order.items.map((i) => { + i.note = "testing 1234" + i.reason = { + value: "test_reason", + id: "rr_test", + } + return i + }) + const segmentOrder = await segmentService.buildOrder(order) + + expect(segmentOrder).toEqual({ + checkout_id: "cart_13", + coupon: undefined, + currency: "DKK", + discount: 0, + email: "test@example.com", + order_id: "12355", + payment_provider: "", + products: [ + { + category: "Collection", + name: "Test", + price: 4.47, + product_id: "prod_123", + quantity: 2, + reporting_revenue: 8.94, + sku: "", + subtitle: "Subtitle", + type: "Type", + variant: "TEST", + reason_id: "rr_test", + reason_value: "test_reason", + note: "testing 1234", + }, + ], + region_id: "reg_123", + reporting_discount: 0, + reporting_revenue: 123.99, + reporting_shipping: 123.99, + reporting_subtotal: 22, + reporting_tax: 0, + reporting_total: 123.99, + revenue: 123.99, + shipping: 123.99, + shipping_city: undefined, + shipping_country: "DK", + shipping_methods: [ + { + name: "standard", + price: 12399, + }, + ], + subtotal: 22, + tax: 0, + total: 123.99, + }) + }) + it("successfully builds order with zero decimal currency", async () => { jest.clearAllMocks() diff --git a/packages/medusa-plugin-segment/src/services/segment.js b/packages/medusa-plugin-segment/src/services/segment.js index bd7eadee2a..89c56c3a57 100644 --- a/packages/medusa-plugin-segment/src/services/segment.js +++ b/packages/medusa-plugin-segment/src/services/segment.js @@ -141,7 +141,7 @@ class SegmentService extends BaseService { { relations: ["collection", "type"] } ) - return { + const toReturn = { name, variant, price: this.rounded_( @@ -155,6 +155,19 @@ class SegmentService extends BaseService { sku, quantity: item.quantity, } + + // If we are building a refund order include details about + // the reason for return + if (item.reason) { + toReturn.reason_id = item.reason.id + toReturn.reason_value = item.reason.value + } + + if (item.note) { + toReturn.note = item.note + } + + return toReturn }) ), } diff --git a/packages/medusa-plugin-segment/src/subscribers/order.js b/packages/medusa-plugin-segment/src/subscribers/order.js index 16de94435c..33f1d2f291 100644 --- a/packages/medusa-plugin-segment/src/subscribers/order.js +++ b/packages/medusa-plugin-segment/src/subscribers/order.js @@ -163,7 +163,9 @@ class OrderSubscriber { ], }) - const ret = await this.returnService_.retrieve(return_id) + const ret = await this.returnService_.retrieve(return_id, { + relations: ["items", "items.reason"], + }) const shipping = [] if (ret.shipping_method && ret.shipping_method.price) { @@ -185,7 +187,17 @@ class OrderSubscriber { const toBuildFrom = { ...order, shipping_methods: shipping, - items: ret.items.map((i) => merged.find((l) => l.id === i.item_id)), + items: ret.items.map((i) => { + const li = merged.find((l) => l.id === i.item_id) + if (i.reason) { + li.reason = i.reason + } + + if (i.note) { + li.note = i.note + } + return li + }), } const orderData = await segmentService.buildOrder(toBuildFrom) diff --git a/packages/medusa-plugin-segment/yarn.lock b/packages/medusa-plugin-segment/yarn.lock index a20c2e86f7..d0621fb20d 100644 --- a/packages/medusa-plugin-segment/yarn.lock +++ b/packages/medusa-plugin-segment/yarn.lock @@ -879,6 +879,18 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@hapi/hoek@^9.0.0": + version "9.2.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131" + integrity sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug== + +"@hapi/topo@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" + integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1071,6 +1083,23 @@ component-type "^1.2.1" join-component "^1.1.0" +"@sideway/address@^4.1.0": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.2.tgz#811b84333a335739d3969cfc434736268170cad1" + integrity sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@sinonjs/commons@^1.7.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d" @@ -2997,6 +3026,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -3487,6 +3521,22 @@ jest@^25.5.2: import-local "^3.0.2" jest-cli "^25.5.4" +joi-objectid@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/joi-objectid/-/joi-objectid-3.0.1.tgz#63ace7860f8e1a993a28d40c40ffd8eff01a3668" + integrity sha512-V/3hbTlGpvJ03Me6DJbdBI08hBTasFOmipsauOsxOSnsF1blxV537WTl1zPwbfcKle4AK0Ma4OPnzMH4LlvTpQ== + +joi@^17.3.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.0.tgz#b5c2277c8519e016316e49ababd41a1908d9ef20" + integrity sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.0" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + join-component@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5" @@ -3726,6 +3776,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +math-random@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== + md5@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" @@ -3740,6 +3795,23 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= +medusa-core-utils@^1.1.16: + version "1.1.16" + resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.16.tgz#e7002d861aebf81dec7bd0654615eefbd55cb530" + integrity sha512-O176mtAILLbwahxJu2dAOZRnz9AzrX6Oa1NDhrtbBvaPuaFZlhxiajwZkP3KM58bGZ9feKfJ4mVuY2Mtsgj3YA== + dependencies: + joi "^17.3.0" + joi-objectid "^3.0.1" + +medusa-test-utils@^1.1.19: + version "1.1.19" + resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.1.19.tgz#f765b6ba39e0bfe6301423a9b39d4e7e3b1ed32b" + integrity sha512-GkGWOUQsrNTm7tv2P7fG9f651+C05cLpy+nuPPSouIAkxpS0mDqeD1VSrHjFnpz1BPUsjwJGWFFAH5Jd8X5yvQ== + dependencies: + "@babel/plugin-transform-classes" "^7.9.5" + medusa-core-utils "^1.1.16" + randomatic "^3.1.1" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -4290,6 +4362,15 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +randomatic@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" diff --git a/packages/medusa-plugin-sendgrid/CHANGELOG.md b/packages/medusa-plugin-sendgrid/CHANGELOG.md index fa8be9cf64..0d6da815f4 100644 --- a/packages/medusa-plugin-sendgrid/CHANGELOG.md +++ b/packages/medusa-plugin-sendgrid/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.21](https://github.com/medusajs/medusa/compare/medusa-plugin-sendgrid@1.1.20...medusa-plugin-sendgrid@1.1.21) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-sendgrid + + + + + ## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-sendgrid@1.1.19...medusa-plugin-sendgrid@1.1.20) (2021-07-02) **Note:** Version bump only for package medusa-plugin-sendgrid diff --git a/packages/medusa-plugin-sendgrid/package.json b/packages/medusa-plugin-sendgrid/package.json index 8c3962ea22..8719558bda 100644 --- a/packages/medusa-plugin-sendgrid/package.json +++ b/packages/medusa-plugin-sendgrid/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-sendgrid", - "version": "1.1.20", + "version": "1.1.21", "description": "SendGrid transactional emails", "main": "index.js", "repository": { @@ -39,8 +39,8 @@ "@sendgrid/mail": "^7.1.1", "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19" + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-plugin-slack-notification/CHANGELOG.md b/packages/medusa-plugin-slack-notification/CHANGELOG.md index 2fe56e54e9..4d913400a5 100644 --- a/packages/medusa-plugin-slack-notification/CHANGELOG.md +++ b/packages/medusa-plugin-slack-notification/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-slack-notification@1.1.19...medusa-plugin-slack-notification@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-slack-notification + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-slack-notification@1.1.18...medusa-plugin-slack-notification@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-plugin-slack-notification diff --git a/packages/medusa-plugin-slack-notification/package-lock.json b/packages/medusa-plugin-slack-notification/package-lock.json index 886dc85ccf..3db285ea1c 100644 --- a/packages/medusa-plugin-slack-notification/package-lock.json +++ b/packages/medusa-plugin-slack-notification/package-lock.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-economic", - "version": "1.1.19", + "version": "1.1.20", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/packages/medusa-plugin-slack-notification/package.json b/packages/medusa-plugin-slack-notification/package.json index 058f83ffd6..734df12683 100644 --- a/packages/medusa-plugin-slack-notification/package.json +++ b/packages/medusa-plugin-slack-notification/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-slack-notification", - "version": "1.1.19", + "version": "1.1.20", "description": "Slack notifications", "main": "index.js", "repository": { @@ -39,8 +39,8 @@ "axios": "^0.19.2", "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19", + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20", "moment": "^2.27.0" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-twilio-sms/CHANGELOG.md b/packages/medusa-plugin-twilio-sms/CHANGELOG.md index 256caf033c..9e4efc4a2a 100644 --- a/packages/medusa-plugin-twilio-sms/CHANGELOG.md +++ b/packages/medusa-plugin-twilio-sms/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-twilio-sms@1.1.19...medusa-plugin-twilio-sms@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-twilio-sms + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-twilio-sms@1.1.18...medusa-plugin-twilio-sms@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-plugin-twilio-sms diff --git a/packages/medusa-plugin-twilio-sms/package.json b/packages/medusa-plugin-twilio-sms/package.json index 0111a47c3b..e6e66463fc 100644 --- a/packages/medusa-plugin-twilio-sms/package.json +++ b/packages/medusa-plugin-twilio-sms/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-twilio-sms", - "version": "1.1.19", + "version": "1.1.20", "main": "index.js", "repository": { "type": "git", @@ -35,8 +35,8 @@ "dependencies": { "@babel/plugin-transform-classes": "^7.9.5", "body-parser": "^1.19.0", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19", + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20", "twilio": "^3.49.1" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa-plugin-wishlist/CHANGELOG.md b/packages/medusa-plugin-wishlist/CHANGELOG.md index 2215ac6ba8..a48e285963 100644 --- a/packages/medusa-plugin-wishlist/CHANGELOG.md +++ b/packages/medusa-plugin-wishlist/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-plugin-wishlist@1.1.19...medusa-plugin-wishlist@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-plugin-wishlist + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-plugin-wishlist@1.1.18...medusa-plugin-wishlist@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-plugin-wishlist diff --git a/packages/medusa-plugin-wishlist/package.json b/packages/medusa-plugin-wishlist/package.json index cc11dedc25..dc9ecd4b31 100644 --- a/packages/medusa-plugin-wishlist/package.json +++ b/packages/medusa-plugin-wishlist/package.json @@ -1,6 +1,6 @@ { "name": "medusa-plugin-wishlist", - "version": "1.1.19", + "version": "1.1.20", "description": "Provides /customers/:id/wishlist to add items to a customr's wishlist", "main": "index.js", "repository": { @@ -37,8 +37,8 @@ "dependencies": { "body-parser": "^1.19.0", "express": "^4.17.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19" + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" } diff --git a/packages/medusa-test-utils/CHANGELOG.md b/packages/medusa-test-utils/CHANGELOG.md index 0926f8347b..9c410fc1bf 100644 --- a/packages/medusa-test-utils/CHANGELOG.md +++ b/packages/medusa-test-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.20](https://github.com/medusajs/medusa/compare/medusa-test-utils@1.1.19...medusa-test-utils@1.1.20) (2021-07-15) + +**Note:** Version bump only for package medusa-test-utils + + + + + ## [1.1.19](https://github.com/medusajs/medusa/compare/medusa-test-utils@1.1.18...medusa-test-utils@1.1.19) (2021-07-02) **Note:** Version bump only for package medusa-test-utils diff --git a/packages/medusa-test-utils/package.json b/packages/medusa-test-utils/package.json index 1d7fc2056a..d2c60f69f8 100644 --- a/packages/medusa-test-utils/package.json +++ b/packages/medusa-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "medusa-test-utils", - "version": "1.1.19", + "version": "1.1.20", "description": "Test utils for Medusa", "main": "dist/index.js", "repository": { @@ -29,7 +29,7 @@ }, "dependencies": { "@babel/plugin-transform-classes": "^7.9.5", - "medusa-core-utils": "^1.1.16", + "medusa-core-utils": "^1.1.17", "randomatic": "^3.1.1" }, "gitHead": "db9d6c0cf55ff60a90415b16bc7582cc4795768f" diff --git a/packages/medusa/CHANGELOG.md b/packages/medusa/CHANGELOG.md index 00447c02ca..8da618bef5 100644 --- a/packages/medusa/CHANGELOG.md +++ b/packages/medusa/CHANGELOG.md @@ -3,6 +3,21 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.30](https://github.com/medusajs/medusa/compare/@medusajs/medusa@1.1.29...@medusajs/medusa@1.1.30) (2021-07-15) + + +### Bug Fixes + +* adds tracking links to customer orders ([c013270](https://github.com/medusajs/medusa/commit/c0132700b78d171d6c7e29e2604b99129c5a1921)) +* allow updating billing address on customer ([5a1cbc6](https://github.com/medusajs/medusa/commit/5a1cbc68b721fe80d223e4ff611ebc81346333d7)) +* better store/customer support ([6342e68](https://github.com/medusajs/medusa/commit/6342e68d069636e5eb4877c7ebf7aac952b5e363)) +* create fulfillment ([0603a86](https://github.com/medusajs/medusa/commit/0603a86d65a528af86bdbdc46227faa2f48a93bb)) +* **medusa:** Resolve issue with soft-delete and unique indexes in DB ([#296](https://github.com/medusajs/medusa/issues/296)) ([6358f8f](https://github.com/medusajs/medusa/commit/6358f8fc756291710a82ce39a47d0cbec1395b87)) + + + + + ## [1.1.29](https://github.com/medusajs/medusa/compare/@medusajs/medusa@1.1.28...@medusajs/medusa@1.1.29) (2021-07-02) **Note:** Version bump only for package @medusajs/medusa diff --git a/packages/medusa/README.md b/packages/medusa/README.md index 958c4099ae..8909fbdb71 100644 --- a/packages/medusa/README.md +++ b/packages/medusa/README.md @@ -36,7 +36,7 @@ The steps can be done in any order. The standard path would probably be: Assuming that shipping methods are static within each region we can display all shipping methods at checkout time. If shipping is dynamically calculated the price of the shipping method may change, we will ask the fulfillment provider for new rates. -Payment details can be entered at any point as long as the final amount is known. If the final amount changes afer the payment details are entered the payment method may therefore be invalidated. +Payment details can be entered at any point as long as the final amount is known. If the final amount changes after the payment details are entered the payment method may therefore be invalidated. Within the store UI you could imagine each step being taken care of by a single button click, which calls all endpoints. diff --git a/packages/medusa/package.json b/packages/medusa/package.json index 1062a802d9..f028fb1f00 100644 --- a/packages/medusa/package.json +++ b/packages/medusa/package.json @@ -1,6 +1,6 @@ { "name": "@medusajs/medusa", - "version": "1.1.29", + "version": "1.1.30", "description": "E-commerce for JAMstack", "main": "dist/index.js", "repository": { @@ -17,11 +17,11 @@ "@babel/cli": "^7.14.3", "@babel/core": "^7.14.3", "@babel/preset-typescript": "^7.13.0", - "babel-preset-medusa-package": "^1.1.10", + "babel-preset-medusa-package": "^1.1.11", "cross-env": "^5.2.1", "eslint": "^6.8.0", "jest": "^25.5.2", - "medusa-interfaces": "^1.1.17", + "medusa-interfaces": "^1.1.18", "nodemon": "^2.0.1", "prettier": "^1.19.1", "supertest": "^4.0.2" @@ -59,8 +59,8 @@ "joi": "^17.3.0", "joi-objectid": "^3.0.1", "jsonwebtoken": "^8.5.1", - "medusa-core-utils": "^1.1.16", - "medusa-test-utils": "^1.1.19", + "medusa-core-utils": "^1.1.17", + "medusa-test-utils": "^1.1.20", "morgan": "^1.9.1", "multer": "^1.4.2", "passport": "^0.4.0", diff --git a/packages/medusa/src/api/middlewares/error-handler.js b/packages/medusa/src/api/middlewares/error-handler.js index 285f349734..2fc414f012 100644 --- a/packages/medusa/src/api/middlewares/error-handler.js +++ b/packages/medusa/src/api/middlewares/error-handler.js @@ -9,6 +9,9 @@ export default () => { let statusCode = 500 switch (err.name) { + case MedusaError.Types.DUPLICATE_ERROR: + statusCode = 409 + break case MedusaError.Types.NOT_ALLOWED: case MedusaError.Types.INVALID_DATA: statusCode = 400 diff --git a/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js b/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js index 216618836b..5e1cbe3b51 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js +++ b/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js @@ -63,6 +63,9 @@ import { defaultFields, defaultRelations } from "." * customer_id: * description: The id of the customer to add on the draft order * type: string + * no_notification_order: + * description: An optional flag passed to the resulting order to determine use of notifications. + * type: boolean * shipping_methods: * description: The shipping methods for the draft order * type: array @@ -123,6 +126,7 @@ export default async (req, res) => { }) .optional(), customer_id: Validator.string().optional(), + no_notification_order: Validator.boolean().optional(), shipping_methods: Validator.array() .items({ option_id: Validator.string().required(), diff --git a/packages/medusa/src/api/routes/admin/draft-orders/index.js b/packages/medusa/src/api/routes/admin/draft-orders/index.js index 10b9e65f30..d5a08f41ce 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/index.js +++ b/packages/medusa/src/api/routes/admin/draft-orders/index.js @@ -78,6 +78,7 @@ export const defaultFields = [ "created_at", "updated_at", "metadata", + "no_notification_order", ] export const allowedFields = [ @@ -89,6 +90,7 @@ export const allowedFields = [ "created_at", "updated_at", "metadata", + "no_notification_order", ] export const allowedRelations = ["cart"] diff --git a/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.js b/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.js index 6230f553d5..5de8e9545a 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.js +++ b/packages/medusa/src/api/routes/admin/draft-orders/update-draft-order.js @@ -35,6 +35,9 @@ import { defaultCartFields, defaultCartRelations, defaultFields } from "." * code: * description: "The code that a Discount is identifed by." * type: string + * no_notification_order: + * description: "An optional flag passed to the resulting order to determine use of notifications." + * type: boolean * customer_id: * description: "The id of the Customer to associate the Draft Order with." * type: string @@ -68,6 +71,7 @@ export default async (req, res) => { }) .optional(), customer_id: Validator.string().optional(), + no_notification_order: Validator.boolean().optional(), }) const { value, error } = schema.validate(req.body) @@ -88,6 +92,13 @@ export default async (req, res) => { ) } + if ("no_notification_order" in value) { + await draftOrderService.update(draftOrder.id, { + no_notification_order: value.no_notification_order, + }) + delete value.no_notification_order + } + await cartService.update(draftOrder.cart_id, value) draftOrder.cart = await cartService.retrieve(draftOrder.cart_id, { diff --git a/packages/medusa/src/api/routes/admin/gift-cards/index.js b/packages/medusa/src/api/routes/admin/gift-cards/index.js index ea3a04f5ee..bb15df5aac 100644 --- a/packages/medusa/src/api/routes/admin/gift-cards/index.js +++ b/packages/medusa/src/api/routes/admin/gift-cards/index.js @@ -33,7 +33,10 @@ export const defaultFields = [ "metadata", ] -export const defaultRelations = ["region"] +export const defaultRelations = [ + "region", + "order", +] export const allowedFields = [ "id", diff --git a/packages/medusa/src/api/routes/admin/gift-cards/list-gift-cards.js b/packages/medusa/src/api/routes/admin/gift-cards/list-gift-cards.js index 10791e6235..28dba7d592 100644 --- a/packages/medusa/src/api/routes/admin/gift-cards/list-gift-cards.js +++ b/packages/medusa/src/api/routes/admin/gift-cards/list-gift-cards.js @@ -1,3 +1,4 @@ +import { MedusaError, Validator } from "medusa-core-utils" import { defaultFields, defaultRelations } from "./" /** @@ -21,14 +22,23 @@ import { defaultFields, defaultRelations } from "./" */ export default async (req, res) => { try { + const limit = parseInt(req.query.limit) || 50 + const offset = parseInt(req.query.offset) || 0 + const selector = {} + if ("q" in req.query) { + selector.q = req.query.q + } + const giftCardService = req.scope.resolve("giftCardService") const giftCards = await giftCardService.list(selector, { select: defaultFields, relations: defaultRelations, order: { created_at: "DESC" }, + limit: limit, + skip: offset, }) res.status(200).json({ gift_cards: giftCards }) diff --git a/packages/medusa/src/api/routes/admin/gift-cards/update-gift-card.js b/packages/medusa/src/api/routes/admin/gift-cards/update-gift-card.js index 6c90578dd2..eb28ec062d 100644 --- a/packages/medusa/src/api/routes/admin/gift-cards/update-gift-card.js +++ b/packages/medusa/src/api/routes/admin/gift-cards/update-gift-card.js @@ -1,4 +1,5 @@ import { MedusaError, Validator } from "medusa-core-utils" +import { defaultFields, defaultRelations } from "./" /** * @oas [post] /gift-cards/{id} diff --git a/packages/medusa/src/api/routes/admin/orders/__tests__/create-fulfillment.js b/packages/medusa/src/api/routes/admin/orders/__tests__/create-fulfillment.js index 971eb227e6..95350aa0d7 100644 --- a/packages/medusa/src/api/routes/admin/orders/__tests__/create-fulfillment.js +++ b/packages/medusa/src/api/routes/admin/orders/__tests__/create-fulfillment.js @@ -42,7 +42,7 @@ describe("POST /admin/orders/:id/fulfillment", () => { quantity: 1, }, ], - undefined + { metadata: undefined, no_notification: undefined } ) }) diff --git a/packages/medusa/src/api/routes/admin/orders/__tests__/get-order.js b/packages/medusa/src/api/routes/admin/orders/__tests__/get-order.js index 5001ed0def..57cb1db7ea 100644 --- a/packages/medusa/src/api/routes/admin/orders/__tests__/get-order.js +++ b/packages/medusa/src/api/routes/admin/orders/__tests__/get-order.js @@ -62,6 +62,7 @@ const defaultFields = [ "total", "paid_total", "refundable_amount", + "no_notification", ] describe("GET /admin/orders", () => { diff --git a/packages/medusa/src/api/routes/admin/orders/__tests__/return-order.js b/packages/medusa/src/api/routes/admin/orders/__tests__/return-order.js index 5a36010d3e..661a5498a9 100644 --- a/packages/medusa/src/api/routes/admin/orders/__tests__/return-order.js +++ b/packages/medusa/src/api/routes/admin/orders/__tests__/return-order.js @@ -1,7 +1,7 @@ import { IdMap } from "medusa-test-utils" import { request } from "../../../../../helpers/test-request" -import { orders } from "../../../../../services/__mocks__/order" import { ReturnService } from "../../../../../services/__mocks__/return" +import { EventBusServiceMock } from "../../../../../services/__mocks__/event-bus" describe("POST /admin/orders/:id/return", () => { describe("successfully returns full order", () => { @@ -21,6 +21,7 @@ describe("POST /admin/orders/:id/return", () => { }, ], refund: 10, + no_notification: true, }, adminSession: { jwt: { @@ -47,6 +48,7 @@ describe("POST /admin/orders/:id/return", () => { }, ], refund_amount: 10, + no_notification: true, shipping_method: undefined, }) }) @@ -69,6 +71,7 @@ describe("POST /admin/orders/:id/return", () => { }, ], refund: -1, + no_notification: true, }, adminSession: { jwt: { @@ -95,6 +98,7 @@ describe("POST /admin/orders/:id/return", () => { }, ], refund_amount: 0, + no_notification: true, shipping_method: undefined, }) }) @@ -118,6 +122,7 @@ describe("POST /admin/orders/:id/return", () => { ], refund: -1, }, + no_notification: true, adminSession: { jwt: { userId: IdMap.getId("admin_user"), @@ -143,6 +148,7 @@ describe("POST /admin/orders/:id/return", () => { }, ], refund_amount: 0, + no_notification: true, shipping_method: undefined, }) }) @@ -165,6 +171,7 @@ describe("POST /admin/orders/:id/return", () => { }, ], refund: 100, + no_notification: true, return_shipping: { option_id: "opt_1234", price: 12, @@ -195,6 +202,7 @@ describe("POST /admin/orders/:id/return", () => { }, ], refund_amount: 100, + no_notification: true, shipping_method: { option_id: "opt_1234", price: 12, @@ -205,4 +213,82 @@ describe("POST /admin/orders/:id/return", () => { expect(ReturnService.fulfill).toHaveBeenCalledWith("return") }) }) + + describe("the api call overrides notification settings of order", () => { + it("eventBus is called with the proper no notification feature", async () => { + jest.clearAllMocks() + const subject = await request( + "POST", + `/admin/orders/${IdMap.getId("test-order")}/return`, + { + payload: { + items: [ + { + item_id: IdMap.getId("existingLine"), + quantity: 10, + }, + ], + refund: 100, + return_shipping: { + option_id: "opt_1234", + price: 12, + }, + no_notification: false, + }, + adminSession: { + jwt: { + userId: IdMap.getId("admin_user"), + }, + }, + } + ) + expect(EventBusServiceMock.emit).toHaveBeenCalledWith( + expect.any(String), + { + id: expect.any(String), + no_notification: false, + return_id: expect.any(String), + } + ) + }) + }) + + describe("the api call inherits notification settings of order", () => { + it("eventBus is called with the proper no notification feature", async () => { + jest.clearAllMocks() + await request( + "POST", + `/admin/orders/${IdMap.getId("test-order")}/return`, + { + payload: { + items: [ + { + item_id: IdMap.getId("existingLine"), + quantity: 10, + }, + ], + refund: 100, + return_shipping: { + option_id: "opt_1234", + price: 12, + }, + }, + adminSession: { + jwt: { + userId: IdMap.getId("admin_user"), + }, + }, + } + ) + + expect(EventBusServiceMock.emit).toHaveBeenCalledWith( + expect.any(String), + { + id: expect.any(String), + no_notification: true, + return_id: expect.any(String), + } + ) + }) + }) }) diff --git a/packages/medusa/src/api/routes/admin/orders/create-claim.js b/packages/medusa/src/api/routes/admin/orders/create-claim.js index ce77c090a4..ade142b418 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-claim.js +++ b/packages/medusa/src/api/routes/admin/orders/create-claim.js @@ -91,6 +91,9 @@ import { defaultRelations, defaultFields } from "./" * refund_amount: * description: The amount to refund the Customer when the Claim type is `refund`. * type: integer + * no_notification: + * description: If set to true no notification will be send related to this Claim. + * type: boolean * metadata: * description: An optional set of key-value pairs to hold additional information. * type: object @@ -108,7 +111,6 @@ import { defaultRelations, defaultFields } from "./" */ export default async (req, res) => { const { id } = req.params - const schema = Validator.object().keys({ type: Validator.string() .valid("replace", "refund") @@ -155,6 +157,7 @@ export default async (req, res) => { .integer() .optional(), shipping_address: Validator.object().optional(), + no_notification: Validator.boolean().optional(), metadata: Validator.object().optional(), }) @@ -162,7 +165,6 @@ export default async (req, res) => { if (error) { throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details) } - const idempotencyKeyService = req.scope.resolve("idempotencyKeyService") const headerKey = req.get("Idempotency-Key") || "" @@ -212,6 +214,7 @@ export default async (req, res) => { return_shipping: value.return_shipping, additional_items: value.additional_items, shipping_methods: value.shipping_methods, + no_notification: value.no_notification, metadata: value.metadata, }) diff --git a/packages/medusa/src/api/routes/admin/orders/create-fulfillment.js b/packages/medusa/src/api/routes/admin/orders/create-fulfillment.js index f8ccab4ac1..11e41323ce 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-fulfillment.js +++ b/packages/medusa/src/api/routes/admin/orders/create-fulfillment.js @@ -24,6 +24,9 @@ import { defaultRelations, defaultFields } from "./" * quantity: * description: The quantity of the Line Item to fulfill. * type: integer + * no_notification: + * description: If set to true no notification will be send related to this Swap. + * type: boolean * metadata: * description: An optional set of key-value pairs to hold additional information. * type: object @@ -49,6 +52,7 @@ export default async (req, res) => { quantity: Validator.number().required(), }) .required(), + no_notification: Validator.boolean().optional(), metadata: Validator.object().optional(), }) @@ -60,7 +64,10 @@ export default async (req, res) => { try { const orderService = req.scope.resolve("orderService") - await orderService.createFulfillment(id, value.items, value.metadata) + await orderService.createFulfillment(id, value.items, { + metadata: value.metadata, + no_notification: value.no_notification, + }) const order = await orderService.retrieve(id, { select: defaultFields, diff --git a/packages/medusa/src/api/routes/admin/orders/create-order.js b/packages/medusa/src/api/routes/admin/orders/create-order.js index e6ff1b36df..5adce02ad8 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-order.js +++ b/packages/medusa/src/api/routes/admin/orders/create-order.js @@ -27,6 +27,7 @@ export default async (req, res) => { items: Validator.array().optional(), }) .required(), + no_notification: Validator.boolean().optional(), metadata: Validator.object().optional(), }) diff --git a/packages/medusa/src/api/routes/admin/orders/create-shipment.js b/packages/medusa/src/api/routes/admin/orders/create-shipment.js index a371ef244f..915e15f26d 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-shipment.js +++ b/packages/medusa/src/api/routes/admin/orders/create-shipment.js @@ -21,6 +21,9 @@ import { defaultRelations, defaultFields } from "./" * type: array * items: * type: string + * no_notification: + * description: If set to true no notification will be send related to this Shipment. + * type: boolean * tags: * - Order * responses: @@ -41,6 +44,7 @@ export default async (req, res) => { tracking_numbers: Validator.array() .items(Validator.string()) .optional(), + no_notification: Validator.boolean().optional(), }) const { value, error } = schema.validate(req.body) @@ -54,7 +58,8 @@ export default async (req, res) => { await orderService.createShipment( id, value.fulfillment_id, - value.tracking_numbers.map(n => ({ tracking_number: n })) + value.tracking_numbers.map(n => ({ tracking_number: n })), + { no_notification: value.no_notification } ) const order = await orderService.retrieve(id, { diff --git a/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.js b/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.js index 702d886cb5..edf8572f51 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.js +++ b/packages/medusa/src/api/routes/admin/orders/create-swap-shipment.js @@ -22,6 +22,9 @@ import { defaultFields, defaultRelations } from "./" * type: array * items: * type: string + * no_notification: + * description: If set to true no notification will be send related to this Claim. + * type: boolean * tags: * - Order * responses: @@ -42,6 +45,7 @@ export default async (req, res) => { tracking_numbers: Validator.array() .items(Validator.string()) .optional(), + no_notification: Validator.boolean().optional(), }) const { value, error } = schema.validate(req.body) @@ -56,7 +60,8 @@ export default async (req, res) => { await swapService.createShipment( swap_id, value.fulfillment_id, - value.tracking_numbers.map(n => ({ tracking_number: n })) + value.tracking_numbers.map(n => ({ tracking_number: n })), + { no_notification: value.no_notification } ) const order = await orderService.retrieve(id, { diff --git a/packages/medusa/src/api/routes/admin/orders/create-swap.js b/packages/medusa/src/api/routes/admin/orders/create-swap.js index 7782400eaa..25ad45604e 100644 --- a/packages/medusa/src/api/routes/admin/orders/create-swap.js +++ b/packages/medusa/src/api/routes/admin/orders/create-swap.js @@ -45,6 +45,9 @@ import { defaultFields, defaultRelations } from "./" * quantity: * description: The quantity of the Product Variant to ship. * type: integer + * no_notification: + * description: If set to true no notification will be send related to this Swap. + * type: boolean * tags: * - Order * responses: @@ -79,6 +82,7 @@ export default async (req, res) => { variant_id: Validator.string().required(), quantity: Validator.number().required(), }), + no_notification: Validator.boolean().optional(), }) const { value, error } = schema.validate(req.body) @@ -134,7 +138,10 @@ export default async (req, res) => { value.return_items, value.additional_items, value.return_shipping, - { idempotency_key: idempotencyKey.idempotency_key } + { + idempotency_key: idempotencyKey.idempotency_key, + no_notification: value.no_notification, + } ) await swapService.withTransaction(manager).createCart(swap.id) diff --git a/packages/medusa/src/api/routes/admin/orders/fulfill-claim.js b/packages/medusa/src/api/routes/admin/orders/fulfill-claim.js index 50668a16c2..6c017c8517 100644 --- a/packages/medusa/src/api/routes/admin/orders/fulfill-claim.js +++ b/packages/medusa/src/api/routes/admin/orders/fulfill-claim.js @@ -17,6 +17,9 @@ import { defaultRelations, defaultFields } from "./" * metadata: * description: An optional set of key-value pairs to hold additional information. * type: object + * no_notification: + * description: If set to true no notification will be send related to this Claim. + * type: boolean * tags: * - Order * responses: @@ -34,6 +37,7 @@ export default async (req, res) => { const schema = Validator.object().keys({ metadata: Validator.object().optional(), + no_notification: Validator.boolean().optional(), }) const { value, error } = schema.validate(req.body) @@ -47,9 +51,10 @@ export default async (req, res) => { const entityManager = req.scope.resolve("manager") await entityManager.transaction(async manager => { - await claimService - .withTransaction(manager) - .createFulfillment(claim_id, value.metadata) + await claimService.withTransaction(manager).createFulfillment(claim_id, { + metadata: value.metadata, + no_notification: value.no_notification, + }) }) const order = await orderService.retrieve(id, { diff --git a/packages/medusa/src/api/routes/admin/orders/fulfill-swap.js b/packages/medusa/src/api/routes/admin/orders/fulfill-swap.js index 7212614f49..aa8f680464 100644 --- a/packages/medusa/src/api/routes/admin/orders/fulfill-swap.js +++ b/packages/medusa/src/api/routes/admin/orders/fulfill-swap.js @@ -17,6 +17,9 @@ import { defaultRelations, defaultFields } from "./" * metadata: * description: An optional set of key-value pairs to hold additional information. * type: object + * no_notification: + * description: If set to true no notification will be send related to this Claim. + * type: boolean * tags: * - Order * responses: @@ -34,6 +37,7 @@ export default async (req, res) => { const schema = Validator.object().keys({ metadata: Validator.object().optional(), + no_notification: Validator.boolean().optional, }) const { value, error } = schema.validate(req.body) @@ -47,9 +51,10 @@ export default async (req, res) => { const entityManager = req.scope.resolve("manager") await entityManager.transaction(async manager => { - await swapService - .withTransaction(manager) - .createFulfillment(swap_id, value.metadata) + await swapService.withTransaction(manager).createFulfillment(swap_id, { + metadata: value.metadata, + no_notification: value.no_notification, + }) const order = await orderService.withTransaction(manager).retrieve(id, { select: defaultFields, diff --git a/packages/medusa/src/api/routes/admin/orders/index.js b/packages/medusa/src/api/routes/admin/orders/index.js index 98e72e599c..29ce86e109 100644 --- a/packages/medusa/src/api/routes/admin/orders/index.js +++ b/packages/medusa/src/api/routes/admin/orders/index.js @@ -237,6 +237,7 @@ export const defaultFields = [ "total", "paid_total", "refundable_amount", + "no_notification", ] export const allowedFields = [ @@ -265,6 +266,7 @@ export const allowedFields = [ "total", "paid_total", "refundable_amount", + "no_notification", ] export const allowedRelations = [ diff --git a/packages/medusa/src/api/routes/admin/orders/refund-payment.js b/packages/medusa/src/api/routes/admin/orders/refund-payment.js index c4629e0987..b0bc76bf9d 100644 --- a/packages/medusa/src/api/routes/admin/orders/refund-payment.js +++ b/packages/medusa/src/api/routes/admin/orders/refund-payment.js @@ -25,6 +25,9 @@ import { defaultRelations, defaultFields } from "./" * note: * description: A not with additional details about the Refund. * type: string + * no_notification: + * description: If set to true no notification will be send related to this Refund. + * type: boolean * tags: * - Order * responses: @@ -47,9 +50,11 @@ export default async (req, res) => { note: Validator.string() .allow("") .optional(), + no_notification: Validator.boolean().optional(), }) const { value, error } = schema.validate(req.body) + if (error) { throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details) } @@ -57,7 +62,13 @@ export default async (req, res) => { try { const orderService = req.scope.resolve("orderService") - await orderService.createRefund(id, value.amount, value.reason, value.note) + await orderService.createRefund( + id, + value.amount, + value.reason, + value.note, + { no_notification: value.no_notification } + ) const order = await orderService.retrieve(id, { select: defaultFields, diff --git a/packages/medusa/src/api/routes/admin/orders/request-return.js b/packages/medusa/src/api/routes/admin/orders/request-return.js index 3c0b49ed9f..1d3e0c0da0 100644 --- a/packages/medusa/src/api/routes/admin/orders/request-return.js +++ b/packages/medusa/src/api/routes/admin/orders/request-return.js @@ -43,6 +43,9 @@ import { defaultRelations, defaultFields } from "./" * receive_now: * description: A flag to indicate if the Return should be registerd as received immediately. * type: boolean + * no_notification: + * description: A flag to indicate if no notifications should be emitted related to the requested Return. + * type: boolean * refund: * description: The amount to refund. * type: integer @@ -79,6 +82,7 @@ export default async (req, res) => { }) .optional(), receive_now: Validator.boolean().default(false), + no_notification: Validator.boolean().optional(), refund: Validator.number() .integer() .optional(), @@ -141,6 +145,13 @@ export default async (req, res) => { } } + let order = await orderService + .withTransaction(manager) + .retrieve(id) + + const evaluatedNoNotification = value.no_notification !== undefined ? value.no_notification : order.no_notification + returnObj.no_notification = evaluatedNoNotification + const createdReturn = await returnService .withTransaction(manager) .create(returnObj) @@ -150,12 +161,13 @@ export default async (req, res) => { .withTransaction(manager) .fulfill(createdReturn.id) } - + await eventBus .withTransaction(manager) .emit("order.return_requested", { id, return_id: createdReturn.id, + no_notification: evaluatedNoNotification }) return { diff --git a/packages/medusa/src/api/routes/admin/orders/update-claim.js b/packages/medusa/src/api/routes/admin/orders/update-claim.js index ffbd4eae46..90346be45c 100644 --- a/packages/medusa/src/api/routes/admin/orders/update-claim.js +++ b/packages/medusa/src/api/routes/admin/orders/update-claim.js @@ -62,6 +62,9 @@ import { defaultRelations, defaultFields } from "./" * price: * description: The price to charge for the Shipping Method * type: integer + * no_notification: + * description: If set to true no notification will be send related to this Swap. + * type: boolean * metadata: * description: An optional set of key-value pairs to hold additional information. * type: object @@ -106,6 +109,7 @@ export default async (req, res) => { .optional(), }) .optional(), + no_notification: Validator.boolean().optional(), metadata: Validator.object().optional(), }) diff --git a/packages/medusa/src/api/routes/admin/orders/update-order.js b/packages/medusa/src/api/routes/admin/orders/update-order.js index 37e321024b..582b1b9a81 100644 --- a/packages/medusa/src/api/routes/admin/orders/update-order.js +++ b/packages/medusa/src/api/routes/admin/orders/update-order.js @@ -23,6 +23,7 @@ export default async (req, res) => { data: Validator.object(), items: Validator.array(), }), + no_notification: Validator.boolean(), }) const { value, error } = schema.validate(req.body) diff --git a/packages/medusa/src/api/routes/admin/returns/receive-return.js b/packages/medusa/src/api/routes/admin/returns/receive-return.js index dce7cf18f4..5baadcc5d6 100644 --- a/packages/medusa/src/api/routes/admin/returns/receive-return.js +++ b/packages/medusa/src/api/routes/admin/returns/receive-return.js @@ -54,6 +54,7 @@ export default async (req, res) => { }) const { value, error } = schema.validate(req.body) + if (error) { throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details) } diff --git a/packages/medusa/src/api/routes/store/customers/__tests__/create-customer.js b/packages/medusa/src/api/routes/store/customers/__tests__/create-customer.js index ff8606cf3b..d42d3ba41b 100644 --- a/packages/medusa/src/api/routes/store/customers/__tests__/create-customer.js +++ b/packages/medusa/src/api/routes/store/customers/__tests__/create-customer.js @@ -1,6 +1,7 @@ import { IdMap } from "medusa-test-utils" import { request } from "../../../../../helpers/test-request" import { CustomerServiceMock } from "../../../../../services/__mocks__/customer" +import { defaultFields, defaultRelations } from "../" describe("POST /store/customers", () => { describe("successfully creates a customer", () => { @@ -34,7 +35,7 @@ describe("POST /store/customers", () => { expect(CustomerServiceMock.retrieve).toHaveBeenCalledTimes(1) expect(CustomerServiceMock.retrieve).toHaveBeenCalledWith( IdMap.getId("lebron"), - { relations: ["shipping_addresses"] } + { relations: defaultRelations, select: defaultFields } ) }) diff --git a/packages/medusa/src/api/routes/store/customers/__tests__/update-customer.js b/packages/medusa/src/api/routes/store/customers/__tests__/update-customer.js index 35c54520c4..baab0d5261 100644 --- a/packages/medusa/src/api/routes/store/customers/__tests__/update-customer.js +++ b/packages/medusa/src/api/routes/store/customers/__tests__/update-customer.js @@ -1,5 +1,6 @@ import { IdMap } from "medusa-test-utils" import { request } from "../../../../../helpers/test-request" +import { defaultFields, defaultRelations } from "../" import { CustomerServiceMock } from "../../../../../services/__mocks__/customer" describe("POST /store/customers/:id", () => { @@ -42,7 +43,7 @@ describe("POST /store/customers/:id", () => { expect(CustomerServiceMock.retrieve).toHaveBeenCalledTimes(1) expect(CustomerServiceMock.retrieve).toHaveBeenCalledWith( IdMap.getId("lebron"), - { relations: ["shipping_addresses"] } + { relations: defaultRelations, select: defaultFields } ) }) @@ -55,6 +56,98 @@ describe("POST /store/customers/:id", () => { }) }) + describe("successfully updates a customer with billing address id", () => { + let subject + beforeAll(async () => { + subject = await request( + "POST", + `/store/customers/${IdMap.getId("lebron")}`, + { + payload: { + billing_address: "test", + }, + clientSession: { + jwt: { + customer_id: IdMap.getId("lebron"), + }, + }, + } + ) + }) + + afterAll(() => { + jest.clearAllMocks() + }) + + it("calls CustomerService update", () => { + expect(CustomerServiceMock.update).toHaveBeenCalledTimes(1) + expect(CustomerServiceMock.update).toHaveBeenCalledWith( + IdMap.getId("lebron"), + { + billing_address: "test", + } + ) + }) + + it("status code 200", () => { + expect(subject.status).toEqual(200) + }) + }) + + describe("successfully updates a customer with billing address object", () => { + let subject + beforeAll(async () => { + subject = await request( + "POST", + `/store/customers/${IdMap.getId("lebron")}`, + { + payload: { + billing_address: { + first_name: "Olli", + last_name: "Juhl", + address_1: "Laksegade", + city: "Copenhagen", + country_code: "dk", + postal_code: "2100", + phone: "+1 (222) 333 4444", + }, + }, + clientSession: { + jwt: { + customer_id: IdMap.getId("lebron"), + }, + }, + } + ) + }) + + afterAll(() => { + jest.clearAllMocks() + }) + + it("calls CustomerService update", () => { + expect(CustomerServiceMock.update).toHaveBeenCalledTimes(1) + expect(CustomerServiceMock.update).toHaveBeenCalledWith( + IdMap.getId("lebron"), + { + billing_address: { + first_name: "Olli", + last_name: "Juhl", + address_1: "Laksegade", + city: "Copenhagen", + country_code: "dk", + postal_code: "2100", + phone: "+1 (222) 333 4444", + }, + } + ) + }) + + it("status code 200", () => { + expect(subject.status).toEqual(200) + }) + }) + describe("fails if not authenticated", () => { let subject beforeAll(async () => { diff --git a/packages/medusa/src/api/routes/store/customers/create-address.js b/packages/medusa/src/api/routes/store/customers/create-address.js index 26c71c387e..390f07e1a2 100644 --- a/packages/medusa/src/api/routes/store/customers/create-address.js +++ b/packages/medusa/src/api/routes/store/customers/create-address.js @@ -1,4 +1,5 @@ import { Validator, MedusaError } from "medusa-core-utils" +import { defaultRelations, defaultFields } from "./" /** * @oas [post] /customers/{id}/addresses @@ -45,7 +46,8 @@ export default async (req, res) => { let customer = await customerService.addAddress(id, value.address) customer = await customerService.retrieve(id, { - relations: ["shipping_addresses"], + relations: defaultRelations, + select: defaultFields, }) res.status(200).json({ customer }) diff --git a/packages/medusa/src/api/routes/store/customers/create-customer.js b/packages/medusa/src/api/routes/store/customers/create-customer.js index 49fa4ee381..671ecfef0a 100644 --- a/packages/medusa/src/api/routes/store/customers/create-customer.js +++ b/packages/medusa/src/api/routes/store/customers/create-customer.js @@ -1,6 +1,7 @@ import jwt from "jsonwebtoken" import { Validator, MedusaError } from "medusa-core-utils" import config from "../../../../config" +import { defaultRelations, defaultFields } from "./" /** * @oas [post] /customers @@ -40,6 +41,7 @@ export default async (req, res) => { if (error) { throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details) } + try { const customerService = req.scope.resolve("customerService") let customer = await customerService.create(value) @@ -50,7 +52,8 @@ export default async (req, res) => { }) customer = await customerService.retrieve(customer.id, { - relations: ["shipping_addresses"], + relations: defaultRelations, + select: defaultFields, }) res.status(200).json({ customer }) diff --git a/packages/medusa/src/api/routes/store/customers/delete-address.js b/packages/medusa/src/api/routes/store/customers/delete-address.js index aa105f041b..4829da15ac 100644 --- a/packages/medusa/src/api/routes/store/customers/delete-address.js +++ b/packages/medusa/src/api/routes/store/customers/delete-address.js @@ -1,3 +1,5 @@ +import { defaultRelations, defaultFields } from "./" + /** * @oas [delete] /customers/{id}/addresses/{address_id} * operationId: DeleteCustomersCustomerAddressesAddress @@ -25,7 +27,8 @@ export default async (req, res) => { try { await customerService.removeAddress(id, address_id) customer = await customerService.retrieve(id, { - relations: ["shipping_addresses"], + relations: defaultRelations, + select: defaultFields, }) res.json({ customer }) diff --git a/packages/medusa/src/api/routes/store/customers/get-customer.js b/packages/medusa/src/api/routes/store/customers/get-customer.js index a8ca49bf67..53db7b0e5e 100644 --- a/packages/medusa/src/api/routes/store/customers/get-customer.js +++ b/packages/medusa/src/api/routes/store/customers/get-customer.js @@ -1,3 +1,5 @@ +import { defaultRelations, defaultFields } from "./" + /** * @oas [get] /customers/{id} * operationId: GetCustomersCustomer @@ -22,7 +24,8 @@ export default async (req, res) => { try { const customerService = req.scope.resolve("customerService") const customer = await customerService.retrieve(id, { - relations: ["shipping_addresses"], + relations: defaultRelations, + select: defaultFields, }) res.json({ customer }) } catch (err) { diff --git a/packages/medusa/src/api/routes/store/customers/index.js b/packages/medusa/src/api/routes/store/customers/index.js index 374bb5a0ba..79938d1ac2 100644 --- a/packages/medusa/src/api/routes/store/customers/index.js +++ b/packages/medusa/src/api/routes/store/customers/index.js @@ -57,3 +57,39 @@ export default (app, container) => { return app } + +export const defaultRelations = ["shipping_addresses", "billing_address"] + +export const defaultFields = [ + "id", + "email", + "first_name", + "last_name", + "billing_address_id", + "phone", + "has_account", + "created_at", + "updated_at", + "deleted_at", + "metadata", +] + +export const allowedRelations = [ + "shipping_addresses", + "billing_address", + "orders", +] + +export const allowedFields = [ + "id", + "email", + "first_name", + "last_name", + "billing_address_id", + "phone", + "has_account", + "created_at", + "updated_at", + "deleted_at", + "metadata", +] diff --git a/packages/medusa/src/api/routes/store/customers/update-address.js b/packages/medusa/src/api/routes/store/customers/update-address.js index 234a1350e0..6c495451a2 100644 --- a/packages/medusa/src/api/routes/store/customers/update-address.js +++ b/packages/medusa/src/api/routes/store/customers/update-address.js @@ -1,4 +1,5 @@ import { Validator, MedusaError } from "medusa-core-utils" +import { defaultRelations, defaultFields } from "./" /** * @oas [post] /customers/{id}/addresses/{address_id} @@ -50,7 +51,8 @@ export default async (req, res) => { ) customer = await customerService.retrieve(id, { - relations: ["shipping_addresses"], + relations: defaultRelations, + select: defaultFields, }) res.json({ customer }) diff --git a/packages/medusa/src/api/routes/store/customers/update-customer.js b/packages/medusa/src/api/routes/store/customers/update-customer.js index 1c67cbc0a2..6101f4fcaa 100644 --- a/packages/medusa/src/api/routes/store/customers/update-customer.js +++ b/packages/medusa/src/api/routes/store/customers/update-customer.js @@ -1,4 +1,5 @@ import { Validator, MedusaError } from "medusa-core-utils" +import { defaultRelations, defaultFields } from "./" /** * @oas [post] /customers/{id} @@ -18,12 +19,19 @@ import { Validator, MedusaError } from "medusa-core-utils" * last_name: * description: "The Customer's last name." * type: string + * billing_address: + * description: "The Address to be used for billing purposes." + * anyOf: + * - $ref: "#/components/schemas/address" * password: * description: "The Customer's password." * type: string * phone: * description: "The Customer's phone number." * type: string + * metadata: + * description: "Metadata about the customer." + * type: object * tags: * - Customer * responses: @@ -40,10 +48,12 @@ export default async (req, res) => { const { id } = req.params const schema = Validator.object().keys({ + billing_address: Validator.address().optional(), first_name: Validator.string().optional(), last_name: Validator.string().optional(), password: Validator.string().optional(), phone: Validator.string().optional(), + metadata: Validator.object().optional(), }) const { value, error } = schema.validate(req.body) @@ -56,7 +66,8 @@ export default async (req, res) => { let customer = await customerService.update(id, value) customer = await customerService.retrieve(customer.id, { - relations: ["shipping_addresses"], + relations: defaultRelations, + select: defaultFields, }) res.status(200).json({ customer }) diff --git a/packages/medusa/src/api/routes/store/orders/index.js b/packages/medusa/src/api/routes/store/orders/index.js index 4405a86ba7..8aaa346bca 100644 --- a/packages/medusa/src/api/routes/store/orders/index.js +++ b/packages/medusa/src/api/routes/store/orders/index.js @@ -30,6 +30,7 @@ export default app => { export const defaultRelations = [ "shipping_address", "fulfillments", + "fulfillments.tracking_links", "items", "items.variant", "items.variant.product", @@ -66,6 +67,7 @@ export const defaultFields = [ export const allowedRelations = [ "shipping_address", "fulfillments", + "fulfillments.tracking_links", "billing_address", "items", "items.variant", diff --git a/packages/medusa/src/index.js b/packages/medusa/src/index.js index c5c3367cd6..e9088f2917 100644 --- a/packages/medusa/src/index.js +++ b/packages/medusa/src/index.js @@ -43,3 +43,4 @@ export { Swap } from "./models/swap" export { User } from "./models/user" export { DraftOrder } from "./models/draft-order" export { ReturnReason } from "./models/return-reason" + diff --git a/packages/medusa/src/migrations/1623231564533-no_notification.ts b/packages/medusa/src/migrations/1623231564533-no_notification.ts new file mode 100644 index 0000000000..dcd56690b0 --- /dev/null +++ b/packages/medusa/src/migrations/1623231564533-no_notification.ts @@ -0,0 +1,25 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class noNotification1623231564533 implements MigrationInterface { + name = 'noNotification1623231564533' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "return" ADD "no_notification" boolean`); + await queryRunner.query(`ALTER TABLE "claim_order" ADD "no_notification" boolean`); + await queryRunner.query(`ALTER TABLE "swap" ADD "no_notification" boolean`); + await queryRunner.query(`ALTER TABLE "order" ADD "no_notification" boolean`); + await queryRunner.query(`ALTER TABLE "draft_order" ADD "no_notification_order" boolean`); + await queryRunner.query(`ALTER TABLE "fulfillment" ADD "no_notification" boolean`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "fulfillment" DROP COLUMN "no_notification"`); + await queryRunner.query(`ALTER TABLE "draft_order" DROP COLUMN "no_notification_order"`); + await queryRunner.query(`ALTER TABLE "order" DROP COLUMN "no_notification"`); + await queryRunner.query(`ALTER TABLE "swap" DROP COLUMN "no_notification"`); + await queryRunner.query(`ALTER TABLE "claim_order" DROP COLUMN "no_notification"`); + await queryRunner.query(`ALTER TABLE "return" DROP COLUMN "no_notification"`); + + } + +} diff --git a/packages/medusa/src/migrations/1624287602631-gc_remove_unique_order.ts b/packages/medusa/src/migrations/1624287602631-gc_remove_unique_order.ts index 21a0ae3a6c..c3fbfd4c4d 100644 --- a/packages/medusa/src/migrations/1624287602631-gc_remove_unique_order.ts +++ b/packages/medusa/src/migrations/1624287602631-gc_remove_unique_order.ts @@ -4,28 +4,16 @@ export class gcRemoveUniqueOrder1624287602631 implements MigrationInterface { name = "gcRemoveUniqueOrder1624287602631" public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "gift_card" DROP CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0"` - ) + await queryRunner.query(`ALTER TABLE "gift_card" DROP CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0"`) await queryRunner.query(`COMMENT ON COLUMN "gift_card"."order_id" IS NULL`) - await queryRunner.query( - `ALTER TABLE "gift_card" DROP CONSTRAINT "REL_dfc1f02bb0552e79076aa58dbb"` - ) - await queryRunner.query( - `ALTER TABLE "gift_card" ADD CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0" FOREIGN KEY ("order_id") REFERENCES "order"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` - ) + await queryRunner.query(`ALTER TABLE "gift_card" DROP CONSTRAINT "REL_dfc1f02bb0552e79076aa58dbb"`) + await queryRunner.query(`ALTER TABLE "gift_card" ADD CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0" FOREIGN KEY ("order_id") REFERENCES "order"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `ALTER TABLE "gift_card" DROP CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0"` - ) - await queryRunner.query( - `ALTER TABLE "gift_card" ADD CONSTRAINT "REL_dfc1f02bb0552e79076aa58dbb" UNIQUE ("order_id")` - ) + await queryRunner.query(`ALTER TABLE "gift_card" DROP CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0"`) + await queryRunner.query(`ALTER TABLE "gift_card" ADD CONSTRAINT "REL_dfc1f02bb0552e79076aa58dbb" UNIQUE ("order_id")`) await queryRunner.query(`COMMENT ON COLUMN "gift_card"."order_id" IS NULL`) - await queryRunner.query( - `ALTER TABLE "gift_card" ADD CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0" FOREIGN KEY ("order_id") REFERENCES "order"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` - ) + await queryRunner.query(`ALTER TABLE "gift_card" ADD CONSTRAINT "FK_dfc1f02bb0552e79076aa58dbb0" FOREIGN KEY ("order_id") REFERENCES "order"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) } } diff --git a/packages/medusa/src/migrations/1624610325746-soft_deleting_unique_constraints.ts b/packages/medusa/src/migrations/1624610325746-soft_deleting_unique_constraints.ts new file mode 100644 index 0000000000..2bfb814c82 --- /dev/null +++ b/packages/medusa/src/migrations/1624610325746-soft_deleting_unique_constraints.ts @@ -0,0 +1,42 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class softDeletingUniqueConstraints1624610325746 implements MigrationInterface { + name = 'softDeletingUniqueConstraints1624610325746' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_6910923cb678fd6e99011a21cc"`); + await queryRunner.query(`DROP INDEX "IDX_db7355f7bd36c547c8a4f539e5"`); + await queryRunner.query(`DROP INDEX "IDX_087926f6fec32903be3c8eedfa"`); + await queryRunner.query(`DROP INDEX "IDX_f4dc2c0888b66d547c175f090e"`); + await queryRunner.query(`DROP INDEX "IDX_9db95c4b71f632fc93ecbc3d8b"`); + await queryRunner.query(`DROP INDEX "IDX_7124082c8846a06a857cca386c"`); + await queryRunner.query(`DROP INDEX "IDX_a0a3f124dc5b167622217fee02"`); + + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_e08af711f3493df1e921c4c9ef" ON "product_collection" ("handle") WHERE deleted_at IS NOT NULL`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_77c4073c30ea7793f484750529" ON "product" ("handle") WHERE deleted_at IS NOT NULL`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_ae3e22c67d7c7a969a363533c0" ON "discount" ("code") WHERE deleted_at IS NOT NULL`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0683952543d7d3f4fffc427034" ON "product_variant" ("sku") WHERE deleted_at IS NOT NULL`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_410649600ce31c10c4b667ca10" ON "product_variant" ("barcode") WHERE deleted_at IS NOT NULL`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5248fda27b9f16ef818604bb6f" ON "product_variant" ("ean") WHERE deleted_at IS NOT NULL`); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_832f86daf8103491d634a967da" ON "product_variant" ("upc") WHERE deleted_at IS NOT NULL`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_ae3e22c67d7c7a969a363533c0"`); + await queryRunner.query(`DROP INDEX "IDX_77c4073c30ea7793f484750529"`); + await queryRunner.query(`DROP INDEX "IDX_e08af711f3493df1e921c4c9ef"`); + await queryRunner.query(`DROP INDEX "IDX_832f86daf8103491d634a967da"`); + await queryRunner.query(`DROP INDEX "IDX_5248fda27b9f16ef818604bb6f"`); + await queryRunner.query(`DROP INDEX "IDX_410649600ce31c10c4b667ca10"`); + await queryRunner.query(`DROP INDEX "IDX_0683952543d7d3f4fffc427034"`); + + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_087926f6fec32903be3c8eedfa" ON "discount" ("code") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_db7355f7bd36c547c8a4f539e5" ON "product" ("handle") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_6910923cb678fd6e99011a21cc" ON "product_collection" ("handle") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_a0a3f124dc5b167622217fee02" ON "product_variant" ("upc") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_7124082c8846a06a857cca386c" ON "product_variant" ("ean") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_9db95c4b71f632fc93ecbc3d8b" ON "product_variant" ("barcode") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_f4dc2c0888b66d547c175f090e" ON "product_variant" ("sku") `); + } + +} diff --git a/packages/medusa/src/models/cart.ts b/packages/medusa/src/models/cart.ts index dbb5f53b53..3190685171 100644 --- a/packages/medusa/src/models/cart.ts +++ b/packages/medusa/src/models/cart.ts @@ -246,7 +246,7 @@ export class Cart { @Column({ type: "jsonb", nullable: true }) context: any - + // Total fields shipping_total: number discount_total: number diff --git a/packages/medusa/src/models/claim-order.ts b/packages/medusa/src/models/claim-order.ts index 547245544f..c5c8ec430b 100644 --- a/packages/medusa/src/models/claim-order.ts +++ b/packages/medusa/src/models/claim-order.ts @@ -134,6 +134,9 @@ export class ClaimOrder { @DeleteDateColumn({ type: "timestamptz" }) deleted_at: Date + @Column({ type: "boolean", nullable: true}) + no_notification: Boolean + @Column({ type: "jsonb", nullable: true }) metadata: any @@ -223,6 +226,9 @@ export class ClaimOrder { * deleted_at: * type: string * format: date-time + * no_notification: + * description: "Flag for describing whether or not notifications related to this should be send." + * type: boolean * metadata: * type: object */ diff --git a/packages/medusa/src/models/discount.ts b/packages/medusa/src/models/discount.ts index b76294bece..21b2e1787e 100644 --- a/packages/medusa/src/models/discount.ts +++ b/packages/medusa/src/models/discount.ts @@ -23,7 +23,7 @@ export class Discount { @PrimaryColumn() id: string - @Index({ unique: true }) + @Index({ unique: true, where: "deleted_at IS NOT NULL" }) @Column() code: string diff --git a/packages/medusa/src/models/draft-order.ts b/packages/medusa/src/models/draft-order.ts index 7430e6ee07..7c49919069 100644 --- a/packages/medusa/src/models/draft-order.ts +++ b/packages/medusa/src/models/draft-order.ts @@ -61,6 +61,9 @@ export class DraftOrder { @Column({ type: "timestamptz", nullable: true }) completed_at: Date + @Column({ nullable: true}) + no_notification_order: boolean + @Column({ type: "jsonb", nullable: true }) metadata: any @@ -115,6 +118,8 @@ export class DraftOrder { * completed_at: * type: string * format: date-time + * no_notification_order: + * type: boolean * metadata: * type: object * idempotency_key: diff --git a/packages/medusa/src/models/fulfillment.ts b/packages/medusa/src/models/fulfillment.ts index 4f14943e90..30fc17986e 100644 --- a/packages/medusa/src/models/fulfillment.ts +++ b/packages/medusa/src/models/fulfillment.ts @@ -62,6 +62,9 @@ export class Fulfillment { @JoinColumn({ name: "order_id" }) order: Order + @Column({ type: "boolean", nullable: true}) + no_notification: Boolean + @Index() @Column() provider_id: string @@ -157,6 +160,9 @@ export class Fulfillment { * description: "The date with timezone at which the Fulfillment was shipped." * type: string * format: date-time + * no_notification: + * description: "Flag for describing whether or not notifications related to this should be send." + * type: boolean * canceled_at: * description: "The date with timezone at which the Fulfillment was canceled." * type: string diff --git a/packages/medusa/src/models/order.ts b/packages/medusa/src/models/order.ts index a6d7be6ff0..6aab13bc40 100644 --- a/packages/medusa/src/models/order.ts +++ b/packages/medusa/src/models/order.ts @@ -245,6 +245,9 @@ export class Order { @Column({ type: "jsonb", nullable: true }) metadata: any + @Column({ type: "boolean", nullable: true}) + no_notification: Boolean + @Column({ nullable: true }) idempotency_key: string @@ -414,4 +417,7 @@ export class Order { * type: integer * paid_total: * type: integer + * no_notification: + * description: "Flag for describing whether or not notifications related to this should be send." + * type: boolean */ diff --git a/packages/medusa/src/models/product-collection.ts b/packages/medusa/src/models/product-collection.ts index 2f9e04f557..3fa79cbfdb 100644 --- a/packages/medusa/src/models/product-collection.ts +++ b/packages/medusa/src/models/product-collection.ts @@ -23,7 +23,7 @@ export class ProductCollection { @Column() title: string - @Index({ unique: true }) + @Index({ unique: true, where: "deleted_at IS NOT NULL" }) @Column({ nullable: true }) handle: string diff --git a/packages/medusa/src/models/product-variant.ts b/packages/medusa/src/models/product-variant.ts index 7b97b6ea2a..fd5730765f 100644 --- a/packages/medusa/src/models/product-variant.ts +++ b/packages/medusa/src/models/product-variant.ts @@ -47,19 +47,19 @@ export class ProductVariant { prices: MoneyAmount[] @Column({ nullable: true }) - @Index({ unique: true }) + @Index({ unique: true, where: "deleted_at IS NOT NULL" }) sku: string - @Index({ unique: true }) @Column({ nullable: true }) + @Index({ unique: true, where: "deleted_at IS NOT NULL" }) barcode: string - @Index({ unique: true }) @Column({ nullable: true }) + @Index({ unique: true, where: "deleted_at IS NOT NULL" }) ean: string - @Index({ unique: true }) @Column({ nullable: true }) + @Index({ unique: true, where: "deleted_at IS NOT NULL" }) upc: string @Column({ type: "int" }) diff --git a/packages/medusa/src/models/product.ts b/packages/medusa/src/models/product.ts index e1f453ae18..9fa2b4e35f 100644 --- a/packages/medusa/src/models/product.ts +++ b/packages/medusa/src/models/product.ts @@ -39,7 +39,7 @@ export class Product { @Column({ nullable: true }) description: string - @Index({ unique: true }) + @Index({ unique: true, where: "deleted_at IS NOT NULL" }) @Column({ nullable: true }) handle: string diff --git a/packages/medusa/src/models/return.ts b/packages/medusa/src/models/return.ts index 77cd1d2837..382f308937 100644 --- a/packages/medusa/src/models/return.ts +++ b/packages/medusa/src/models/return.ts @@ -99,6 +99,9 @@ export class Return { @UpdateDateColumn({ type: "timestamptz" }) updated_at: Date + @Column({ type: "boolean", nullable: true}) + no_notification: Boolean + @Column({ type: "jsonb", nullable: true }) metadata: any @@ -165,6 +168,9 @@ export class Return { * description: "The date with timezone at which the resource was last updated." * type: string * format: date-time + * no_notification: + * description: "When set to true, no notification will be sent related to this return." + * type: boolean * metadata: * description: "An optional key-value map with additional information." * type: object diff --git a/packages/medusa/src/models/swap.ts b/packages/medusa/src/models/swap.ts index 606bdfade7..8bac4bda79 100644 --- a/packages/medusa/src/models/swap.ts +++ b/packages/medusa/src/models/swap.ts @@ -130,6 +130,9 @@ export class Swap { @DeleteDateColumn({ type: "timestamptz" }) deleted_at: Date + @Column({ type: "boolean", nullable: true}) + no_notification: Boolean + @Column({ type: "jsonb", nullable: true }) metadata: any @@ -224,6 +227,9 @@ export class Swap { * description: "The date with timezone at which the resource was last updated." * type: string * format: date-time + * no_notification: + * description: "If set to true, no notification will be sent related to this swap" + * type: boolean * metadata: * description: "An optional key-value map with additional information." * type: object diff --git a/packages/medusa/src/repositories/gift-card.ts b/packages/medusa/src/repositories/gift-card.ts index 578dc8ed58..f3ebcf9afa 100644 --- a/packages/medusa/src/repositories/gift-card.ts +++ b/packages/medusa/src/repositories/gift-card.ts @@ -1,5 +1,61 @@ -import { EntityRepository, Repository } from "typeorm" +import { flatten, groupBy, map, merge } from "lodash" +import { EntityRepository, FindManyOptions, Repository } from "typeorm" import { GiftCard } from "../models/gift-card" @EntityRepository(GiftCard) -export class GiftCardRepository extends Repository {} +export class GiftCardRepository extends Repository { + public async findWithRelations( + relations: Array = [], + idsOrOptionsWithoutRelations: Omit< + FindManyOptions, + "relations" + > = {} + ): Promise { + let entities + if (Array.isArray(idsOrOptionsWithoutRelations)) { + entities = await this.findByIds(idsOrOptionsWithoutRelations) + } else { + entities = await this.find(idsOrOptionsWithoutRelations) + } + const entitiesIds = entities.map(({ id }) => id) + + const groupedRelations = {} + for (const rel of relations) { + const [topLevel] = rel.split(".") + if (groupedRelations[topLevel]) { + groupedRelations[topLevel].push(rel) + } else { + groupedRelations[topLevel] = [rel] + } + } + + const entitiesIdsWithRelations = await Promise.all( + Object.entries(groupedRelations).map(([_, rels]) => { + return this.findByIds(entitiesIds, { + select: ["id"], + relations: rels as string[], + }) + }) + ).then(flatten) + const entitiesAndRelations = entitiesIdsWithRelations.concat(entities) + + const entitiesAndRelationsById = groupBy(entitiesAndRelations, "id") + return map(entitiesAndRelationsById, entityAndRelations => + merge({}, ...entityAndRelations) + ) + } + + public async findOneWithRelations( + relations: Array = [], + optionsWithoutRelations: Omit, "relations"> = {} + ): Promise { + // Limit 1 + optionsWithoutRelations.take = 1 + + const result = await this.findWithRelations( + relations, + optionsWithoutRelations + ) + return result[0] + } +} diff --git a/packages/medusa/src/services/__mocks__/order.js b/packages/medusa/src/services/__mocks__/order.js index bd8d0d6c05..5779f64e3b 100644 --- a/packages/medusa/src/services/__mocks__/order.js +++ b/packages/medusa/src/services/__mocks__/order.js @@ -47,6 +47,7 @@ export const orders = { providerid: "default_provider", data: {}, }, + no_notification: true, shipping_method: [ { providerid: "default_provider", @@ -99,6 +100,7 @@ export const orders = { payment_method: { providerid: "default_provider", }, + no_notification: false, shipping_methods: [ { id: IdMap.getId("expensiveShipping"), diff --git a/packages/medusa/src/services/__tests__/claim.js b/packages/medusa/src/services/__tests__/claim.js index cedc534746..feae278cb3 100644 --- a/packages/medusa/src/services/__tests__/claim.js +++ b/packages/medusa/src/services/__tests__/claim.js @@ -22,6 +22,7 @@ describe("ClaimService", () => { order: { id: "1234", region_id: "order_region", + no_notification: true, items: [ { id: "itm_1", @@ -113,6 +114,7 @@ describe("ClaimService", () => { quantity: 1, }, ], + no_notification: true, }) expect(withTransactionMock).toHaveBeenCalledWith("lineItem") @@ -138,6 +140,7 @@ describe("ClaimService", () => { expect(claimRepo.create).toHaveBeenCalledTimes(1) expect(claimRepo.create).toHaveBeenCalledWith({ payment_status: "not_refunded", + no_notification: true, refund_amount: 1000, type: "refund", order_id: "1234", @@ -156,6 +159,7 @@ describe("ClaimService", () => { expect(eventBusService.emit).toHaveBeenCalledTimes(1) expect(eventBusService.emit).toHaveBeenCalledWith("claim.created", { id: "claim_134", + no_notification: true, }) }) @@ -208,6 +212,25 @@ describe("ClaimService", () => { }) ).rejects.toThrow(`Claims must have at least one claim item.`) }) + + it.each( + [ + [false, false], + [undefined, true], + ], + "passes correct no_notification status to event bus", + async (input, expected) => { + await claimService.create({ + ...testClaim, + no_notification: input, + }) + + expect(eventBusService.emit).toHaveBeenCalledWith(expect.any(String), { + id: expect.any(String), + no_notification: expected, + }) + } + ) }) describe("retrieve", () => { @@ -294,7 +317,9 @@ describe("ClaimService", () => { }) it("successfully creates fulfillment", async () => { - await claimService.createFulfillment("claim_id", { meta: "data" }) + await claimService.createFulfillment("claim_id", { + metadata: { meta: "data" }, + }) expect(withTransactionMock).toHaveBeenCalledTimes(3) expect(withTransactionMock).toHaveBeenCalledWith("eventBus") @@ -414,7 +439,10 @@ describe("ClaimService", () => { ) await claimService.createShipment("claim", "ful_123", ["track1234"], { - meta: "data", + metadata: { + meta: "data", + }, + no_notification: false, }) expect(withTransactionMock).toHaveBeenCalledTimes(3) @@ -426,7 +454,12 @@ describe("ClaimService", () => { expect(fulfillmentService.createShipment).toHaveBeenCalledWith( "ful_123", ["track1234"], - { meta: "data" } + { + metadata: { + meta: "data", + }, + no_notification: false, + } ) expect(lineItemService.update).toHaveBeenCalledTimes(1) diff --git a/packages/medusa/src/services/__tests__/customer.js b/packages/medusa/src/services/__tests__/customer.js index d23c10dc52..e980cda5a3 100644 --- a/packages/medusa/src/services/__tests__/customer.js +++ b/packages/medusa/src/services/__tests__/customer.js @@ -168,8 +168,14 @@ describe("CustomerService", () => { }, }) + const addressRepository = MockRepository({ + create: data => data, + save: data => Promise.resolve(data), + }) + const customerService = new CustomerService({ manager: MockManager, + addressRepository, customerRepository, eventBusService, }) @@ -233,7 +239,7 @@ describe("CustomerService", () => { last_name: "Juhl", address_1: "Laksegade", city: "Copenhagen", - country_code: "DK", + country_code: "dk", postal_code: "2100", phone: "+1 (222) 333 4444", }, diff --git a/packages/medusa/src/services/__tests__/draft-order.js b/packages/medusa/src/services/__tests__/draft-order.js index ab5460f553..dceedd6091 100644 --- a/packages/medusa/src/services/__tests__/draft-order.js +++ b/packages/medusa/src/services/__tests__/draft-order.js @@ -1,5 +1,6 @@ import _ from "lodash" -import { IdMap, MockRepository, MockManager } from "medusa-test-utils" +import { MockRepository, MockManager } from "medusa-test-utils" +import { EventBusServiceMock } from "../__mocks__/event-bus" import DraftOrderService from "../draft-order" const eventBusService = { @@ -205,4 +206,93 @@ describe("DraftOrderService", () => { } }) }) + + describe("update", () => { + const testOrder = { + region_id: "test-region", + shipping_address_id: "test-shipping", + billing_address_id: "test-billing", + customer_id: "test-customer", + items: [{ variant_id: "test-variant", quantity: 2, metadata: {} }], + shipping_methods: [ + { + option_id: "test-option", + data: {}, + }, + ], + } + + const completedOrder = { + status: "completed", + ...testOrder, + } + + const draftOrderRepository = MockRepository({ + create: d => ({ + ...d, + }), + save: d => ({ + id: "test-draft-order", + ...d, + }), + findOne: q => { + switch (q.where.id) { + case "completed": + return Promise.resolve(completedOrder) + default: + return Promise.resolve(testOrder) + } + }, + }) + + const draftOrderService = new DraftOrderService({ + manager: MockManager, + regionService: undefined, + cartService: undefined, + shippingOptionService: undefined, + lineItemService: undefined, + productVariantService: undefined, + draftOrderRepository, + addressRepository: undefined, + eventBusService: EventBusServiceMock, + }) + + beforeEach(async () => { + jest.clearAllMocks() + }) + + it("calls draftOrder model functions", async () => { + await draftOrderService.update("test-draft-order", { + no_notification_order: true, + }) + + expect(draftOrderRepository.save).toHaveBeenCalledTimes(1) + expect(draftOrderRepository.save).toHaveBeenCalledWith({ + no_notification_order: true, + billing_address_id: "test-billing", + customer_id: "test-customer", + items: [ + { + metadata: {}, + quantity: 2, + variant_id: "test-variant", + }, + ], + region_id: "test-region", + shipping_address_id: "test-shipping", + shipping_methods: [ + { + data: {}, + option_id: "test-option", + }, + ], + }) + }) + + it("fails to update draftOrder when already complete", async () => { + await expect(draftOrderService.update("completed", {})).rejects.toThrow( + "Can't update a draft order which is complete" + ) + }) + }) }) diff --git a/packages/medusa/src/services/__tests__/gift-card.js b/packages/medusa/src/services/__tests__/gift-card.js new file mode 100644 index 0000000000..792edec5e3 --- /dev/null +++ b/packages/medusa/src/services/__tests__/gift-card.js @@ -0,0 +1,256 @@ +import { IdMap, MockManager, MockRepository } from "medusa-test-utils" + +import GiftCardService from "../gift-card" + +describe("GiftCardService", () => { + const eventBusService = { + emit: jest.fn(), + withTransaction: function() { + return this + }, + } + + describe("create", () => { + const giftCardRepo = MockRepository({ + create: s => { + return Promise.resolve(s) + }, + save: s => { + return Promise.resolve(s) + }, + }) + + const regionService = { + withTransaction: function() { + return this + }, + retrieve: () => { + return Promise.resolve({ + id: IdMap.getId("region-id"), + }) + }, + } + + const giftCardService = new GiftCardService({ + manager: MockManager, + giftCardRepository: giftCardRepo, + regionService: regionService, + eventBusService: eventBusService, + }) + + const giftCard = { + region_id: IdMap.getId("region-id"), + order_id: IdMap.getId("order-id"), + is_disabled: true, + } + + beforeEach(async () => { + jest.clearAllMocks() + }) + + it("correctly creates a giftcard", async () => { + await giftCardService.create(giftCard) + + expect(giftCardRepo.create).toHaveBeenCalledTimes(1) + expect(giftCardRepo.create).toHaveBeenCalledWith({ + region_id: IdMap.getId("region-id"), + order_id: IdMap.getId("order-id"), + is_disabled: true, + code: expect.any(String), + }) + }) + + it("fails to create giftcard if no region is provided", async () => { + const card = { + ...giftCard, + } + + card.region_id = undefined + + await expect(giftCardService.create(card)).rejects.toThrow( + "Gift card is missing region_id" + ) + }) + }) + + describe("retrieve", () => { + const giftCardRepo = MockRepository({ + findOneWithRelations: () => { + return Promise.resolve({}) + }, + }) + + beforeEach(async () => { + jest.clearAllMocks() + }) + + const giftCardService = new GiftCardService({ + manager: MockManager, + giftCardRepository: giftCardRepo, + }) + + it("it calls order model functions", async () => { + await giftCardService.retrieve(IdMap.getId("gift-card"), { + relations: ["region"], + select: ["id"], + }) + + expect(giftCardRepo.findOneWithRelations).toHaveBeenCalledTimes(1) + expect(giftCardRepo.findOneWithRelations).toHaveBeenCalledWith( + ["region"], + { + where: { + id: IdMap.getId("gift-card"), + }, + select: ["id"], + } + ) + }) + }) + + describe("retrieveByCode", () => { + const giftCardRepo = MockRepository({ + findOneWithRelations: () => { + return Promise.resolve({}) + }, + }) + + beforeEach(async () => { + jest.clearAllMocks() + }) + + const giftCardService = new GiftCardService({ + manager: MockManager, + giftCardRepository: giftCardRepo, + }) + + it("it calls order model functions", async () => { + await giftCardService.retrieveByCode("1234-1234-1234-1234", { + relations: ["region"], + select: ["id"], + }) + + expect(giftCardRepo.findOneWithRelations).toHaveBeenCalledTimes(1) + expect(giftCardRepo.findOneWithRelations).toHaveBeenCalledWith( + ["region"], + { + where: { + code: "1234-1234-1234-1234", + }, + select: ["id"], + } + ) + }) + }) + + describe("update", () => { + const giftCard = { + region_id: IdMap.getId("region-id"), + order_id: IdMap.getId("order-id"), + is_disabled: true, + value: 5000, + } + + const giftCardRepo = MockRepository({ + findOneWithRelations: s => { + return Promise.resolve(giftCard) + }, + save: s => { + return Promise.resolve(s) + }, + }) + + const regionService = { + withTransaction: function() { + return this + }, + retrieve: () => { + return Promise.resolve({ + id: IdMap.getId("other-region"), + }) + }, + } + + const giftCardService = new GiftCardService({ + manager: MockManager, + giftCardRepository: giftCardRepo, + regionService: regionService, + }) + + beforeEach(async () => { + jest.clearAllMocks() + }) + + it("calls order model functions", async () => { + await giftCardService.update(IdMap.getId("giftcard-id"), { + is_disabled: false, + region_id: IdMap.getId("other-region"), + }) + + expect(giftCardRepo.save).toHaveBeenCalledTimes(1) + expect(giftCardRepo.save).toHaveBeenCalledWith({ + region_id: IdMap.getId("other-region"), + order_id: IdMap.getId("order-id"), + is_disabled: false, + value: 5000, + }) + }) + + it.each([[-100], [6000]])( + "fails to update balance with illegal input '%s'", + async input => { + await expect( + giftCardService.update(IdMap.getId("giftcard-id"), { + balance: input, + }) + ).rejects.toThrow("new balance is invalid") + } + ) + }) + + describe("delete", () => { + const giftCard = { + region_id: IdMap.getId("region-id"), + order_id: IdMap.getId("order-id"), + } + + const giftCardRepo = MockRepository({ + findOne: s => { + switch (s.where.id) { + case IdMap.getId("gift-card"): + return Promise.resolve(giftCard) + default: + return Promise.resolve() + } + }, + softRemove: s => { + return Promise.resolve() + }, + }) + + const giftCardService = new GiftCardService({ + manager: MockManager, + giftCardRepository: giftCardRepo, + }) + + beforeEach(async () => { + jest.clearAllMocks() + }) + + it("successfully deletes existing gift-card", async () => { + await giftCardService.delete(IdMap.getId("gift-card")) + + expect(giftCardRepo.softRemove).toHaveBeenCalledTimes(1) + expect(giftCardRepo.softRemove).toHaveBeenCalledWith({ + region_id: IdMap.getId("region-id"), + order_id: IdMap.getId("order-id"), + }) + }) + + it("returns if no gift-card found", async () => { + await giftCardService.delete(IdMap.getId("other")) + + expect(giftCardRepo.softRemove).toHaveBeenCalledTimes(0) + }) + }) +}) diff --git a/packages/medusa/src/services/__tests__/notification.js b/packages/medusa/src/services/__tests__/notification.js index f26ab26d15..64b6361b65 100644 --- a/packages/medusa/src/services/__tests__/notification.js +++ b/packages/medusa/src/services/__tests__/notification.js @@ -1,30 +1,31 @@ import NotificationService from "../notification" -import { IdMap, MockManager, MockRepository } from "medusa-test-utils" +import { MockManager, MockRepository } from "medusa-test-utils" describe("NotificationService", () => { - describe("send", () => { - const notificationRepository = MockRepository({ create: c => c }) + const notificationRepository = MockRepository({ create: c => c }) - const container = { - manager: MockManager, - notificationRepository, - noti_test: { - sendNotification: jest.fn(() => - Promise.resolve({ - to: "test@mail.com", - data: { id: "something" }, - }) - ), - }, - } + const container = { + manager: MockManager, + notificationRepository, + noti_test: { + sendNotification: jest.fn(() => + Promise.resolve({ + to: "test@mail.com", + data: { id: "something" }, + }) + ), + }, + } - const notificationService = new NotificationService(container) + beforeEach(() => { + jest.clearAllMocks() + }) - beforeEach(() => { - jest.clearAllMocks() - }) + describe("send", () =>{ it("successfully calls provider and saves noti", async () => { + const notificationService = new NotificationService(container) + await notificationService.send("event.test", { id: "test" }, "test") expect(container.noti_test.sendNotification).toHaveBeenCalledTimes(1) @@ -51,4 +52,30 @@ describe("NotificationService", () => { expect(notificationRepository.save).toHaveBeenCalledWith(constructed) }) }) + + describe("handleEvent", () => { + + it("cancels notification if no_notification is set", async () => { + const notificationService = new NotificationService(container) + const event = "event.test" + notificationService.subscribe(event, "test") + + await notificationService.handleEvent(event, {id: "id", + return_id: "id", + no_notification: true}) + + expect(container.noti_test.sendNotification).not.toHaveBeenCalled() + }) + + it("if no_notification is not set notification is send", async () => { + const notificationService = new NotificationService(container) + const event = "event.test" + notificationService.subscribe(event, "test") + + await notificationService.handleEvent(event, {id: "id", return_id: "id"}) + + expect(container.noti_test.sendNotification).toHaveBeenCalledTimes(1) + }) + + }) }) diff --git a/packages/medusa/src/services/__tests__/order.js b/packages/medusa/src/services/__tests__/order.js index 6e9755094a..e9667752ba 100644 --- a/packages/medusa/src/services/__tests__/order.js +++ b/packages/medusa/src/services/__tests__/order.js @@ -711,6 +711,7 @@ describe("OrderService", () => { const order = { fulfillments: [], shipping_methods: [{ id: "ship" }], + no_notification: true, items: [ { id: "item_1", @@ -859,6 +860,31 @@ describe("OrderService", () => { fulfillment_status: "partially_fulfilled", }) }) + + it.each([ + [true, true], + [false, false], + [undefined, true], + ])( + "emits correct no_notification option with '%s'", + async (input, expected) => { + await orderService.createFulfillment( + "test-order", + [ + { + item_id: "item_1", + quantity: 1, + }, + ], + { no_notification: input } + ) + + expect(eventBusService.emit).toHaveBeenCalledWith(expect.any(String), { + id: expect.any(String), + no_notification: expected, + }) + } + ) }) describe("registerReturnReceived", () => { @@ -975,6 +1001,7 @@ describe("OrderService", () => { fulfilled_quantity: 0, }, ], + no_notification: true, } const orderRepo = MockRepository({ @@ -996,7 +1023,11 @@ describe("OrderService", () => { } const fulfillmentService = { - retrieve: () => Promise.resolve({ order_id: IdMap.getId("test") }), + retrieve: () => + Promise.resolve({ + order_id: IdMap.getId("test"), + no_notification: true, + }), createShipment: jest .fn() .mockImplementation((shipmentId, tracking, meta) => { @@ -1036,10 +1067,12 @@ describe("OrderService", () => { ) expect(fulfillmentService.createShipment).toHaveBeenCalledTimes(1) - expect(fulfillmentService.createShipment).toHaveBeenCalledWith( + expect( + fulfillmentService.createShipment + ).toHaveBeenCalledWith( IdMap.getId("fulfillment"), [{ tracking_number: "1234" }, { tracking_number: "2345" }], - {} + { metadata: undefined, no_notification: true } ) expect(orderRepo.save).toHaveBeenCalledTimes(1) @@ -1048,6 +1081,27 @@ describe("OrderService", () => { fulfillment_status: "shipped", }) }) + + it.each([ + [true, true], + [false, false], + [undefined, true], + ])( + "emits correct no_notification option with '%s'", + async (input, expected) => { + await orderService.createShipment( + IdMap.getId("test"), + IdMap.getId("fulfillment"), + [{ tracking_number: "1234" }, { tracking_number: "2345" }], + { no_notification: input } + ) + + expect(eventBusService.emit).toHaveBeenCalledWith(expect.any(String), { + id: expect.any(String), + no_notification: expected, + }) + } + ) }) describe("createRefund", () => { @@ -1081,6 +1135,7 @@ describe("OrderService", () => { paid_total: 100, refundable_amount: 100, refunded_total: 0, + no_notification: true, }) }, }) @@ -1129,5 +1184,27 @@ describe("OrderService", () => { ) ).rejects.toThrow("Cannot refund more than the original order amount") }) + + it.each([ + [false, false], + [undefined, true], + ])( + "emits correct no_notification option with '%s'", + async (input, expected) => { + await orderService.createRefund( + IdMap.getId("order_123"), + 100, + "discount", + "note", + { no_notification: input } + ) + + expect(eventBusService.emit).toHaveBeenCalledWith(expect.any(String), { + id: expect.any(String), + no_notification: expected, + refund_id: expect.any(String), + }) + } + ) }) }) diff --git a/packages/medusa/src/services/__tests__/product-collection.js b/packages/medusa/src/services/__tests__/product-collection.js index c2648d2f60..1aa6f1c9fa 100644 --- a/packages/medusa/src/services/__tests__/product-collection.js +++ b/packages/medusa/src/services/__tests__/product-collection.js @@ -135,8 +135,8 @@ describe("ProductCollectionService", () => { it("successfully removes a product collection", async () => { await productCollectionService.delete(IdMap.getId("bathrobe")) - expect(productCollectionRepository.remove).toHaveBeenCalledTimes(1) - expect(productCollectionRepository.remove).toHaveBeenCalledWith({ + expect(productCollectionRepository.softRemove).toHaveBeenCalledTimes(1) + expect(productCollectionRepository.softRemove).toHaveBeenCalledWith({ id: IdMap.getId("bathrobe"), }) }) diff --git a/packages/medusa/src/services/__tests__/swap.js b/packages/medusa/src/services/__tests__/swap.js index cce77b2d7c..da17fad783 100644 --- a/packages/medusa/src/services/__tests__/swap.js +++ b/packages/medusa/src/services/__tests__/swap.js @@ -57,6 +57,7 @@ const testOrder = generateOrder( currency_code: "dkk", region_id: IdMap.getId("region"), tax_rate: 0, + no_notification: true, shipping_address: { first_name: "test", last_name: "testson", @@ -329,6 +330,7 @@ describe("SwapService", () => { order_id: IdMap.getId("test"), fulfillment_status: "not_fulfilled", payment_status: "not_paid", + no_notification: true, additional_items: [ { unit_price: 100, @@ -340,6 +342,31 @@ describe("SwapService", () => { expect(returnService.create).toHaveBeenCalledTimes(1) }) + + it.each([ + [true, true], + [false, false], + [undefined, true], + ])( + "passes correct no_notification to eventBus with %s", + async (input, expected) => { + await swapService.create( + testOrder, + [{ item_id: IdMap.getId("line"), quantity: 1 }], + [{ variant_id: IdMap.getId("new-variant"), quantity: 1 }], + { + id: IdMap.getId("return-shipping"), + price: 20, + }, + { no_notification: input } + ) + + expect(eventBusService.emit).toHaveBeenCalledWith( + expect.any(String), + { id: undefined, no_notification: expected } + ) + } + ) }) }) diff --git a/packages/medusa/src/services/claim.js b/packages/medusa/src/services/claim.js index 758586815b..72cb5491ce 100644 --- a/packages/medusa/src/services/claim.js +++ b/packages/medusa/src/services/claim.js @@ -101,7 +101,7 @@ class ClaimService extends BaseService { const claimRepo = manager.getCustomRepository(this.claimRepository_) const claim = await this.retrieve(id, { relations: ["shipping_methods"] }) - const { claim_items, shipping_methods, metadata } = data + const { claim_items, shipping_methods, metadata, no_notification } = data if (metadata) { claim.metadata = this.setMetadata_(claim, metadata) @@ -135,6 +135,11 @@ class ClaimService extends BaseService { } } + if (no_notification !== undefined) { + claim.no_notification = no_notification + await claimRepo.save(claim) + } + if (claim_items) { for (const i of claim_items) { if (i.id) { @@ -149,6 +154,7 @@ class ClaimService extends BaseService { .withTransaction(manager) .emit(ClaimService.Events.UPDATED, { id: claim.id, + no_notification: claim.no_notification, }) return claim @@ -174,6 +180,7 @@ class ClaimService extends BaseService { refund_amount, shipping_address, shipping_address_id, + no_notification, ...rest } = data @@ -233,6 +240,9 @@ class ClaimService extends BaseService { ) ) + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : order.no_notification + const created = claimRepo.create({ shipping_address_id: addressId, payment_status: type === "refund" ? "not_refunded" : "na", @@ -241,6 +251,7 @@ class ClaimService extends BaseService { type, additional_items: newItems, order_id: order.id, + no_notification: evaluatedNoNotification, }) const result = await claimRepo.save(created) @@ -281,6 +292,7 @@ class ClaimService extends BaseService { metadata: ci.metadata, })), shipping_method: return_shipping, + no_notification: evaluatedNoNotification, }) } @@ -288,13 +300,22 @@ class ClaimService extends BaseService { .withTransaction(manager) .emit(ClaimService.Events.CREATED, { id: result.id, + no_notification: result.no_notification, }) return result }) } - createFulfillment(id, metadata = {}) { + createFulfillment( + id, + config = { + metadata: {}, + no_notification: undefined, + } + ) { + const { metadata, no_notification } = config + return this.atomicPhase_(async manager => { const claim = await this.retrieve(id, { relations: [ @@ -331,6 +352,9 @@ class ClaimService extends BaseService { ) } + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : claim.no_notification + const fulfillments = await this.fulfillmentService_ .withTransaction(manager) .createFulfillment( @@ -347,6 +371,7 @@ class ClaimService extends BaseService { items: claim.additional_items, shipping_methods: claim.shipping_methods, is_claim: true, + no_notification: evaluatedNoNotification, }, claim.additional_items.map(i => ({ item_id: i.id, @@ -395,6 +420,7 @@ class ClaimService extends BaseService { .emit(ClaimService.Events.FULFILLMENT_CREATED, { id: id, fulfillment_id: fulfillment.id, + no_notification: claim.no_notification, }) } @@ -430,21 +456,38 @@ class ClaimService extends BaseService { .withTransaction(manager) .emit(ClaimService.Events.REFUND_PROCESSED, { id, + no_notification: result.no_notification, }) return result }) } - async createShipment(id, fulfillmentId, trackingLinks, metadata = []) { + async createShipment( + id, + fulfillmentId, + trackingLinks, + config = { + metadata: {}, + no_notification: undefined, + } + ) { + const { metadata, no_notification } = config + return this.atomicPhase_(async manager => { const claim = await this.retrieve(id, { relations: ["additional_items"], }) + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : claim.no_notification + const shipment = await this.fulfillmentService_ .withTransaction(manager) - .createShipment(fulfillmentId, trackingLinks, metadata) + .createShipment(fulfillmentId, trackingLinks, { + metadata, + no_notification: evaluatedNoNotification, + }) claim.fulfillment_status = "shipped" @@ -474,6 +517,7 @@ class ClaimService extends BaseService { .emit(ClaimService.Events.SHIPMENT_CREATED, { id, fulfillment_id: shipment.id, + no_notification: evaluatedNoNotification, }) return result @@ -524,6 +568,7 @@ class ClaimService extends BaseService { .withTransaction(manager) .emit(ClaimService.Events.CANCELED, { id: result.id, + no_notification: result.no_notification, }) return result diff --git a/packages/medusa/src/services/customer.js b/packages/medusa/src/services/customer.js index cd9a3b47ca..88ade052b8 100644 --- a/packages/medusa/src/services/customer.js +++ b/packages/medusa/src/services/customer.js @@ -318,6 +318,13 @@ class CustomerService extends BaseService { const existing = await this.retrieveByEmail(email).catch(err => undefined) + if (existing && existing.has_account) { + throw new MedusaError( + MedusaError.Types.DUPLICATE_ERROR, + "A customer with the given email already has an account. Log in instead" + ) + } + if (existing && password && !existing.has_account) { const hashedPassword = await this.hashPassword_(password) customer.password_hash = hashedPassword @@ -360,6 +367,7 @@ class CustomerService extends BaseService { const customerRepository = manager.getCustomRepository( this.customerRepository_ ) + const addrRepo = manager.getCustomRepository(this.addressRepository_) const customer = await this.retrieve(customerId) @@ -368,6 +376,7 @@ class CustomerService extends BaseService { password, password_hash, billing_address, + billing_address_id, metadata, ...rest } = update @@ -380,8 +389,9 @@ class CustomerService extends BaseService { customer.email = this.validateEmail_(email) } - if (billing_address) { - customer.billing_address = this.validateBillingAddress_(billing_address) + if ("billing_address_id" in update || "billing_address" in update) { + const address = update.billing_address_id || update.billing_address + await this.updateBillingAddress_(customer, address, addrRepo) } for (const [key, value] of Object.entries(rest)) { @@ -393,6 +403,7 @@ class CustomerService extends BaseService { } const updated = await customerRepository.save(customer) + await this.eventBus_ .withTransaction(manager) .emit(CustomerService.Events.UPDATED, updated) @@ -400,6 +411,41 @@ class CustomerService extends BaseService { }) } + /** + * Updates the customers's billing address. + * @param {Customer} customer - the Customer to update + * @param {object} address - the value to set the billing address to + * @return {Promise} the result of the update operation + */ + async updateBillingAddress_(customer, addressOrId, addrRepo) { + if (typeof addressOrId === `string`) { + addressOrId = await addrRepo.findOne({ + where: { id: addressOrId }, + }) + } + + addressOrId.country_code = addressOrId.country_code.toLowerCase() + + if (addressOrId.id) { + customer.billing_address_id = addressOrId.id + customer.billing_address = addressOrId + } else { + if (customer.billing_address_id) { + const addr = await addrRepo.findOne({ + where: { id: customer.billing_address_id }, + }) + + await addrRepo.save({ ...addr, ...addressOrId }) + } else { + const created = addrRepo.create({ + ...addressOrId, + }) + const saved = await addrRepo.save(created) + customer.billing_address = saved + } + } + } + async updateAddress(customerId, addressId, address) { return this.atomicPhase_(async manager => { const addressRepo = manager.getCustomRepository(this.addressRepository_) diff --git a/packages/medusa/src/services/draft-order.js b/packages/medusa/src/services/draft-order.js index e04f3ad794..d16044b43b 100644 --- a/packages/medusa/src/services/draft-order.js +++ b/packages/medusa/src/services/draft-order.js @@ -10,6 +10,7 @@ import { Brackets } from "typeorm" class DraftOrderService extends BaseService { static Events = { CREATED: "draft_order.created", + UPDATED: "draft_order.updated", } constructor({ @@ -248,7 +249,13 @@ class DraftOrderService extends BaseService { ) } - const { items, shipping_methods, discounts, ...rest } = data + const { + items, + shipping_methods, + discounts, + no_notification_order, + ...rest + } = data if (discounts) { for (const { code } of discounts) { @@ -263,7 +270,10 @@ class DraftOrderService extends BaseService { .withTransaction(manager) .create({ type: "draft_order", ...rest }) - const draftOrder = draftOrderRepo.create({ cart_id: createdCart.id }) + const draftOrder = draftOrderRepo.create({ + cart_id: createdCart.id, + no_notification_order, + }) const result = await draftOrderRepo.save(draftOrder) await this.eventBus_ @@ -335,6 +345,44 @@ class DraftOrderService extends BaseService { await draftOrderRepo.save(draftOrder) }) } + + /** + * Updates a draft order with the given data + * @param {String} doId - id of the draft order + * @param {DraftOrder} data - values to update the order with + * @returns {Promise} the updated draft order + */ + async update(doId, data) { + return this.atomicPhase_(async manager => { + const doRepo = manager.getCustomRepository(this.draftOrderRepository_) + const draftOrder = await this.retrieve(doId) + let touched = false + + if (draftOrder.status === "completed") { + throw new MedusaError( + MedusaError.Types.NOT_ALLOWED, + "Can't update a draft order which is complete" + ) + } + + if (data.no_notification_order !== undefined) { + touched = true + draftOrder.no_notification_order = data.no_notification_order + } + + if (touched) { + doRepo.save(draftOrder) + + await this.eventBus_ + .withTransaction(manager) + .emit(DraftOrderService.Events.UPDATED, { + id: draftOrder.id, + }) + } + + return draftOrder + }) + } } export default DraftOrderService diff --git a/packages/medusa/src/services/fulfillment.js b/packages/medusa/src/services/fulfillment.js index b05363978d..64183e6aca 100644 --- a/packages/medusa/src/services/fulfillment.js +++ b/packages/medusa/src/services/fulfillment.js @@ -241,10 +241,19 @@ class FulfillmentService extends BaseService { * tracking numbers and potentially more metadata. * @param {Order} fulfillmentId - the fulfillment to ship * @param {TrackingLink[]} trackingNumbers - tracking numbers for the shipment - * @param {object} metadata - potential metadata to add + * @param {object} config - potential configuration settings, such as no_notification and metadata * @return {Fulfillment} the shipped fulfillment */ - async createShipment(fulfillmentId, trackingLinks, metadata) { + async createShipment( + fulfillmentId, + trackingLinks, + config = { + metadata: {}, + no_notification: undefined, + } + ) { + const { metadata, no_notification } = config + return this.atomicPhase_(async manager => { const fulfillmentRepository = manager.getCustomRepository( this.fulfillmentRepository_ @@ -264,6 +273,10 @@ class FulfillmentService extends BaseService { trackingLinkRepo.create(tl) ) + if (no_notification) { + fulfillment.no_notification = no_notification + } + fulfillment.metadata = { ...fulfillment.metadata, ...metadata, diff --git a/packages/medusa/src/services/gift-card.js b/packages/medusa/src/services/gift-card.js index ecd62cf045..173a3d1aee 100644 --- a/packages/medusa/src/services/gift-card.js +++ b/packages/medusa/src/services/gift-card.js @@ -1,7 +1,8 @@ import _ from "lodash" import randomize from "randomatic" import { BaseService } from "medusa-interfaces" -import { Validator, MedusaError } from "medusa-core-utils" +import { Brackets } from "typeorm" +import { MedusaError } from "medusa-core-utils" /** * Provides layer to manipulate gift cards. @@ -72,6 +73,7 @@ class GiftCardService extends BaseService { /** * @param {Object} selector - the query object for find + * @param {Object} config - the configuration used to find the objects. contains relations, skip, and take. * @return {Promise} the result of the find operation */ async list(selector = {}, config = { relations: [], skip: 0, take: 10 }) { @@ -79,8 +81,41 @@ class GiftCardService extends BaseService { this.giftCardRepository_ ) + let q + if ("q" in selector) { + q = selector.q + delete selector.q + } + const query = this.buildQuery_(selector, config) - return giftCardRepo.find(query) + + const rels = query.relations + delete query.relations + + if (q) { + const where = query.where + delete where.id + + const raw = await giftCardRepo + .createQueryBuilder("gift_card") + .leftJoinAndSelect("gift_card.order", "order") + .select(["gift_card.id"]) + .where(where) + .andWhere( + new Brackets(qb => { + return qb + .where(`gift_card.code ILIKE :q`, { q: `%${q}%` }) + .orWhere(`display_id::varchar(255) ILIKE :dId`, { dId: `${q}` }) + }) + ) + .getMany() + + return giftCardRepo.findWithRelations( + rels, + raw.map(i => i.id) + ) + } + return giftCardRepo.findWithRelations(rels, query) } async createTransaction(data) { @@ -156,7 +191,10 @@ class GiftCardService extends BaseService { query.relations = config.relations } - const giftCard = await giftCardRepo.findOne(query) + const rels = query.relations + delete query.relations + + const giftCard = await giftCardRepo.findOneWithRelations(rels, query) if (!giftCard) { throw new MedusaError( @@ -185,7 +223,10 @@ class GiftCardService extends BaseService { query.relations = config.relations } - const giftCard = await giftCardRepo.findOne(query) + const rels = query.relations + delete query.relations + + const giftCard = await giftCardRepo.findOneWithRelations(rels, query) if (!giftCard) { throw new MedusaError( @@ -209,7 +250,7 @@ class GiftCardService extends BaseService { const giftCard = await this.retrieve(giftCardId) - const { region_id, metadata, ...rest } = update + const { region_id, metadata, balance, ...rest } = update if (region_id && region_id !== giftCard.region_id) { const region = await this.regionService_.retrieve(region_id) @@ -220,6 +261,16 @@ class GiftCardService extends BaseService { giftCard.metadata = await this.setMetadata_(giftCard.id, metadata) } + if (balance) { + if (balance < 0 || giftCard.value < balance) { + throw new MedusaError( + MedusaError.Types.INVALID_ARGUMENT, + "new balance is invalid" + ) + } + giftCard.balance = balance + } + for (const [key, value] of Object.entries(rest)) { giftCard[key] = value } diff --git a/packages/medusa/src/services/notification.js b/packages/medusa/src/services/notification.js index 0c4a5eb747..8dcf7962a0 100644 --- a/packages/medusa/src/services/notification.js +++ b/packages/medusa/src/services/notification.js @@ -164,6 +164,9 @@ class NotificationService extends BaseService { if (!subs) { return Promise.resolve() } + if (data["no_notification"] === true) { + return + } return Promise.all( subs.map(async providerId => { diff --git a/packages/medusa/src/services/order.js b/packages/medusa/src/services/order.js index f6e91bd37d..4b09a74a4a 100644 --- a/packages/medusa/src/services/order.js +++ b/packages/medusa/src/services/order.js @@ -333,7 +333,6 @@ class OrderService extends BaseService { const rels = query.relations delete query.relations const raw = await orderRepo.findOneWithRelations(rels, query) - if (!raw) { throw new MedusaError( MedusaError.Types.NOT_FOUND, @@ -408,6 +407,7 @@ class OrderService extends BaseService { OrderService.Events.COMPLETED, { id: orderId, + no_notification: order.no_notification, } ) @@ -507,6 +507,7 @@ class OrderService extends BaseService { .retrieveByCartId(cart.id) toCreate.draft_order_id = draft.id + toCreate.no_notification = draft.no_notification_order } const o = await orderRepo.create(toCreate) @@ -553,6 +554,7 @@ class OrderService extends BaseService { .withTransaction(manager) .emit(OrderService.Events.PLACED, { id: result.id, + no_notification: result.no_notification, }) return result @@ -571,7 +573,17 @@ class OrderService extends BaseService { * the fulfillment * @return {order} the resulting order following the update. */ - async createShipment(orderId, fulfillmentId, trackingLinks, metadata = {}) { + async createShipment( + orderId, + fulfillmentId, + trackingLinks, + config = { + metadata: {}, + no_notification: undefined, + } + ) { + const { metadata, no_notification } = config + return this.atomicPhase_(async manager => { const order = await this.retrieve(orderId, { relations: ["items"] }) const shipment = await this.fulfillmentService_.retrieve(fulfillmentId) @@ -583,9 +595,17 @@ class OrderService extends BaseService { ) } + const evaluatedNoNotification = + no_notification !== undefined + ? no_notification + : shipment.no_notification + const shipmentRes = await this.fulfillmentService_ .withTransaction(manager) - .createShipment(fulfillmentId, trackingLinks, metadata) + .createShipment(fulfillmentId, trackingLinks, { + metadata, + no_notification: evaluatedNoNotification, + }) order.fulfillment_status = "shipped" for (const item of order.items) { @@ -614,6 +634,7 @@ class OrderService extends BaseService { .emit(OrderService.Events.SHIPMENT_CREATED, { id: orderId, fulfillment_id: shipmentRes.id, + no_notification: evaluatedNoNotification, }) return result @@ -634,6 +655,7 @@ class OrderService extends BaseService { .withTransaction(manager) .emit(OrderService.Events.PLACED, { id: result.id, + no_notification: order.no_notification, }) return result }) @@ -801,6 +823,10 @@ class OrderService extends BaseService { await this.updateBillingAddress_(order, update.billing_address) } + if ("no_notification" in update) { + order.no_notification = update.no_notification + } + if ("items" in update) { for (const item of update.items) { await this.lineItemService_.withTransaction(manager).create({ @@ -821,6 +847,7 @@ class OrderService extends BaseService { .withTransaction(manager) .emit(OrderService.Events.UPDATED, { id: orderId, + no_notification: order.no_notification, }) return result }) @@ -871,6 +898,7 @@ class OrderService extends BaseService { .withTransaction(manager) .emit(OrderService.Events.CANCELED, { id: order.id, + no_notification: order.no_notification, }) return result }) @@ -899,6 +927,7 @@ class OrderService extends BaseService { id: orderId, payment_id: p.id, error: err, + no_notification: order.no_notification, }) }) @@ -924,6 +953,7 @@ class OrderService extends BaseService { .withTransaction(manager) .emit(OrderService.Events.PAYMENT_CAPTURED, { id: result.id, + no_notification: order.no_notification, }) } @@ -970,8 +1000,21 @@ class OrderService extends BaseService { * @param {string} orderId - id of order to cancel. * @return {Promise} result of the update operation. */ - async createFulfillment(orderId, itemsToFulfill, metadata = {}) { + async createFulfillment( + orderId, + itemsToFulfill, + config = { + no_notification: undefined, + metadata: {}, + } + ) { + const { metadata, no_notification } = config + return this.atomicPhase_(async manager => { + // NOTE: we are telling the service to calculate all totals for us which + // will add to what is fetched from the database. We want this to happen + // so that we get all order details. These will thereafter be forwarded + // to the fulfillment provider. const order = await this.retrieve(orderId, { select: [ "subtotal", @@ -1007,6 +1050,7 @@ class OrderService extends BaseService { .withTransaction(manager) .createFulfillment(order, itemsToFulfill, { metadata, + no_notification: no_notification, order_id: orderId, }) let successfullyFulfilled = [] @@ -1046,12 +1090,16 @@ class OrderService extends BaseService { order.fulfillments = [...order.fulfillments, ...fulfillments] const result = await orderRepo.save(order) + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : order.no_notification + for (const fulfillment of fulfillments) { await this.eventBus_ .withTransaction(manager) .emit(OrderService.Events.FULFILLMENT_CREATED, { id: orderId, fulfillment_id: fulfillment.id, + no_notification: evaluatedNoNotification, }) } @@ -1107,7 +1155,17 @@ class OrderService extends BaseService { /** * Refunds a given amount back to the customer. */ - async createRefund(orderId, refundAmount, reason, note) { + async createRefund( + orderId, + refundAmount, + reason, + note, + config = { + no_notification: undefined, + } + ) { + const { no_notification } = config + return this.atomicPhase_(async manager => { const order = await this.retrieve(orderId, { select: ["refundable_amount", "total", "refunded_total"], @@ -1126,9 +1184,14 @@ class OrderService extends BaseService { .refundPayment(order.payments, refundAmount, reason, note) const result = await this.retrieve(orderId) + + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : order.no_notification + this.eventBus_.emit(OrderService.Events.REFUND_CREATED, { id: result.id, refund_id: refund.id, + no_notification: evaluatedNoNotification, }) return result }) @@ -1232,6 +1295,7 @@ class OrderService extends BaseService { .emit(OrderService.Events.RETURN_ACTION_REQUIRED, { id: result.id, return_id: receivedReturn.id, + no_notification: receivedReturn.no_notification, }) return result } @@ -1263,6 +1327,7 @@ class OrderService extends BaseService { .emit(OrderService.Events.ITEMS_RETURNED, { id: order.id, return_id: receivedReturn.id, + no_notification: receivedReturn.no_notification, }) return result }) diff --git a/packages/medusa/src/services/product-collection.js b/packages/medusa/src/services/product-collection.js index 5dbd7f34d7..cd9173c641 100644 --- a/packages/medusa/src/services/product-collection.js +++ b/packages/medusa/src/services/product-collection.js @@ -129,7 +129,7 @@ class ProductCollectionService extends BaseService { if (!collection) return Promise.resolve() - await productCollectionRepo.remove(collection) + await productCollectionRepo.softRemove(collection) return Promise.resolve() }) diff --git a/packages/medusa/src/services/return.js b/packages/medusa/src/services/return.js index c3399d8718..c7ae661064 100644 --- a/packages/medusa/src/services/return.js +++ b/packages/medusa/src/services/return.js @@ -330,6 +330,7 @@ class ReturnService extends BaseService { reason_id: i.reason_id, note: i.note, metadata: i.metadata, + no_notification: data.no_notification, }) ) diff --git a/packages/medusa/src/services/swap.js b/packages/medusa/src/services/swap.js index ce149eb325..b12cf4477e 100644 --- a/packages/medusa/src/services/swap.js +++ b/packages/medusa/src/services/swap.js @@ -16,6 +16,7 @@ class SwapService extends BaseService { PAYMENT_CAPTURE_FAILED: "swap.payment_capture_failed", PROCESS_REFUND_FAILED: "swap.process_refund_failed", REFUND_PROCESSED: "swap.refund_processed", + FULFILLMENT_CREATED: "swap.fulfillment_created", } constructor({ @@ -210,6 +211,9 @@ class SwapService extends BaseService { * the customer. * @param {ReturnShipping?} returnShipping - an optional shipping method for * returning the returnItems. + * @param {Object} custom - contains relevant custom information. This object may + * include no_notification which will disable sending notification when creating + * swap. If set, it overrules the attribute inherited from the order. * @returns {Promise} the newly created swap. */ async create( @@ -217,8 +221,11 @@ class SwapService extends BaseService { returnItems, additionalItems, returnShipping, - custom = {} + custom = { + no_notification: undefined, + } ) { + const { no_notification, ...rest } = custom return this.atomicPhase_(async manager => { if ( order.fulfillment_status === "not_fulfilled" || @@ -240,13 +247,17 @@ class SwapService extends BaseService { }) ) + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : order.no_notification + const swapRepo = manager.getCustomRepository(this.swapRepository_) const created = swapRepo.create({ - ...custom, + ...rest, fulfillment_status: "not_fulfilled", payment_status: "not_paid", order_id: order.id, additional_items: newItems, + no_notification: evaluatedNoNotification, }) const result = await swapRepo.save(created) @@ -256,12 +267,14 @@ class SwapService extends BaseService { order_id: order.id, items: returnItems, shipping_method: returnShipping, + no_notification: evaluatedNoNotification, }) await this.eventBus_ .withTransaction(manager) .emit(SwapService.Events.CREATED, { id: result.id, + no_notification: evaluatedNoNotification, }) return result @@ -298,9 +311,14 @@ class SwapService extends BaseService { } catch (err) { swap.payment_status = "requires_action" const result = await swapRepo.save(swap) + await this.eventBus_ .withTransaction(manager) - .emit(SwapService.Events.PROCESS_REFUND_FAILED, result) + .emit(SwapService.Events.PROCESS_REFUND_FAILED, { + id: result.id, + no_notification: swap.no_notification, + }) + return result } @@ -310,7 +328,11 @@ class SwapService extends BaseService { await this.eventBus_ .withTransaction(manager) - .emit(SwapService.Events.REFUND_PROCESSED, result) + .emit(SwapService.Events.REFUND_PROCESSED, { + id: result.id, + no_notification: swap.no_notification, + }) + return result } else if (swap.difference_due === 0) { if (swap.payment_status === "difference_refunded") { @@ -320,9 +342,14 @@ class SwapService extends BaseService { swap.payment_status = "difference_refunded" const result = await swapRepo.save(swap) + await this.eventBus_ .withTransaction(manager) - .emit(SwapService.Events.REFUND_PROCESSED, result) + .emit(SwapService.Events.REFUND_PROCESSED, { + id: result.id, + no_notification: swap.no_notification, + }) + return result } @@ -337,18 +364,28 @@ class SwapService extends BaseService { } catch (err) { swap.payment_status = "requires_action" const result = await swapRepo.save(swap) + await this.eventBus_ .withTransaction(manager) - .emit(SwapService.Events.PAYMENT_CAPTURE_FAILED, result) + .emit(SwapService.Events.PAYMENT_CAPTURE_FAILED, { + id: swap.id, + no_notification: swap.no_notification, + }) + return result } swap.payment_status = "captured" const result = await swapRepo.save(swap) + await this.eventBus_ .withTransaction(manager) - .emit(SwapService.Events.PAYMENT_CAPTURED, result) + .emit(SwapService.Events.PAYMENT_CAPTURED, { + id: result.id, + no_notification: swap.no_notification, + }) + return result }) } @@ -361,6 +398,10 @@ class SwapService extends BaseService { swap.metadata = this.setMetadata_(swap, update.metadata) } + if ("no_notification" in update) { + swap.no_notification = update.no_notification + } + if ("shipping_address" in update) { await this.updateShippingAddress_(swap, update.shipping_address) } @@ -562,6 +603,7 @@ class SwapService extends BaseService { .withTransaction(manager) .emit(SwapService.Events.PAYMENT_COMPLETED, { id: swap.id, + no_notification: swap.no_notification, }) return result @@ -609,10 +651,18 @@ class SwapService extends BaseService { * Fulfills the addtional items associated with the swap. Will call the * fulfillment providers associated with the shipping methods. * @param {string} swapId - the id of the swap to fulfill, - * @param {object} metadata - optional metadata to attach to the fulfillment. + * @param {object} config - optional configurations, includes optional metadata to attach to the shipment, and a no_notification flag. * @returns {Promise} the updated swap with new status and fulfillments. */ - async createFulfillment(swapId, metadata = {}) { + async createFulfillment( + swapId, + config = { + metadata: {}, + no_notification: undefined, + } + ) { + const { metadata, no_notification } = config + return this.atomicPhase_(async manager => { const swap = await this.retrieve(swapId, { relations: [ @@ -642,6 +692,9 @@ class SwapService extends BaseService { ) } + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : swap.no_notification + swap.fulfillments = await this.fulfillmentService_ .withTransaction(manager) .createFulfillment( @@ -658,6 +711,7 @@ class SwapService extends BaseService { items: swap.additional_items, shipping_methods: swap.shipping_methods, is_swap: true, + no_notification: evaluatedNoNotification, }, swap.additional_items.map(i => ({ item_id: i.id, @@ -700,6 +754,17 @@ class SwapService extends BaseService { const swapRepo = manager.getCustomRepository(this.swapRepository_) const result = await swapRepo.save(swap) + + await this.eventBus_.withTransaction(manager).emit( + SwapService.Events.FULFILLMENT_CREATED, + + { + id: swapId, + fulfillment_id: result.id, + no_notification: evaluatedNoNotification, + } + ) + return result }) } @@ -711,19 +776,35 @@ class SwapService extends BaseService { * has been shipped * @param {TrackingLink[]} trackingLinks - the tracking numbers associated * with the shipment - * @param {object} metadata - optional metadata to attach to the shipment. + * @param {object} config - optional configurations, includes optional metadata to attach to the shipment, and a noNotification flag. * @returns {Promise} the updated swap with new fulfillments and status. */ - async createShipment(swapId, fulfillmentId, trackingLinks, metadata = {}) { + async createShipment( + swapId, + fulfillmentId, + trackingLinks, + config = { + metadata: {}, + no_notification: undefined, + } + ) { + const { metadata, no_notification } = config + return this.atomicPhase_(async manager => { const swap = await this.retrieve(swapId, { relations: ["additional_items"], }) + const evaluatedNoNotification = + no_notification !== undefined ? no_notification : swap.no_notification + // Update the fulfillment to register const shipment = await this.fulfillmentService_ .withTransaction(manager) - .createShipment(fulfillmentId, trackingLinks, metadata) + .createShipment(fulfillmentId, trackingLinks, { + metadata, + no_notification: evaluatedNoNotification, + }) swap.fulfillment_status = "shipped" @@ -753,6 +834,7 @@ class SwapService extends BaseService { .emit(SwapService.Events.SHIPMENT_CREATED, { id: swapId, fulfillment_id: shipment.id, + no_notification: swap.no_notification, }) return result }) @@ -809,6 +891,7 @@ class SwapService extends BaseService { .emit(SwapService.Events.RECEIVED, { id: id, order_id: result.order_id, + no_notification: swap.no_notification, }) return result