From e3d8eea3cd2ffd8ec59b6428f6687857afb176c1 Mon Sep 17 00:00:00 2001 From: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Wed, 9 Sep 2020 16:55:34 +0200 Subject: [PATCH] (feat): Adds phone number to Customer --- .../routes/admin/customers/create-customer.js | 1 + .../routes/admin/customers/get-customer.js | 8 ++- .../routes/admin/customers/update-customer.js | 7 ++- .../routes/store/customers/create-customer.js | 2 + .../routes/store/customers/get-customer.js | 2 +- .../routes/store/customers/update-customer.js | 9 +-- .../medusa/src/models/__mocks__/customer.js | 12 ++++ packages/medusa/src/models/customer.js | 1 + .../medusa/src/services/__tests__/customer.js | 22 +++++++ packages/medusa/src/services/customer.js | 20 +++++++ packages/medusa/yarn.lock | 60 +++++++++++++++---- 11 files changed, 125 insertions(+), 19 deletions(-) diff --git a/packages/medusa/src/api/routes/admin/customers/create-customer.js b/packages/medusa/src/api/routes/admin/customers/create-customer.js index 1d4f0378f6..094267f07d 100644 --- a/packages/medusa/src/api/routes/admin/customers/create-customer.js +++ b/packages/medusa/src/api/routes/admin/customers/create-customer.js @@ -8,6 +8,7 @@ export default async (req, res) => { first_name: Validator.string().required(), last_name: Validator.string().required(), password: Validator.string().required(), + phone: Validator.string().optional(), }) const { value, error } = schema.validate(req.body) diff --git a/packages/medusa/src/api/routes/admin/customers/get-customer.js b/packages/medusa/src/api/routes/admin/customers/get-customer.js index c028d89795..5ca5b26b32 100644 --- a/packages/medusa/src/api/routes/admin/customers/get-customer.js +++ b/packages/medusa/src/api/routes/admin/customers/get-customer.js @@ -5,7 +5,13 @@ export default async (req, res) => { let customer = await customerService.retrieve(id) customer = await customerService.decorate( customer, - ["email", "payment_methods", "has_account", "shipping_addresses"], + [ + "email", + "payment_methods", + "has_account", + "shipping_addresses", + "phone", + ], ["orders"] ) diff --git a/packages/medusa/src/api/routes/admin/customers/update-customer.js b/packages/medusa/src/api/routes/admin/customers/update-customer.js index bde5a7c3ce..458de02f47 100644 --- a/packages/medusa/src/api/routes/admin/customers/update-customer.js +++ b/packages/medusa/src/api/routes/admin/customers/update-customer.js @@ -4,9 +4,10 @@ export default async (req, res) => { const { id } = req.params const schema = Validator.object().keys({ - first_name: Validator.string(), - last_name: Validator.string(), - password: Validator.string(), + first_name: Validator.string().optional(), + last_name: Validator.string().optional(), + password: Validator.string().optional(), + phone: Validator.string().optional(), }) const { value, error } = schema.validate(req.body) 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 ad3321bd4d..c96c25d528 100644 --- a/packages/medusa/src/api/routes/store/customers/create-customer.js +++ b/packages/medusa/src/api/routes/store/customers/create-customer.js @@ -10,6 +10,7 @@ export default async (req, res) => { first_name: Validator.string().required(), last_name: Validator.string().required(), password: Validator.string().required(), + phone: Validator.string().optional(), }) const { value, error } = schema.validate(req.body) @@ -36,6 +37,7 @@ export default async (req, res) => { "shipping_addresses", "first_name", "last_name", + "phone", ]) res.status(201).json({ customer: data }) } catch (err) { 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 3f7f32d808..3ad715c2bf 100644 --- a/packages/medusa/src/api/routes/store/customers/get-customer.js +++ b/packages/medusa/src/api/routes/store/customers/get-customer.js @@ -5,7 +5,7 @@ export default async (req, res) => { let customer = await customerService.retrieve(id) customer = customerService.decorate( customer, - ["email", "first_name", "last_name", "shipping_addresses"], + ["email", "first_name", "last_name", "shipping_addresses", "phone"], ["orders"] ) 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 e39b411893..f463a31ecc 100644 --- a/packages/medusa/src/api/routes/store/customers/update-customer.js +++ b/packages/medusa/src/api/routes/store/customers/update-customer.js @@ -4,9 +4,10 @@ export default async (req, res) => { const { id } = req.params const schema = Validator.object().keys({ - first_name: Validator.string(), - last_name: Validator.string(), - password: Validator.string(), + first_name: Validator.string().optional(), + last_name: Validator.string().optional(), + password: Validator.string().optional(), + phone: Validator.string().optional(), }) const { value, error } = schema.validate(req.body) @@ -19,7 +20,7 @@ export default async (req, res) => { const customer = await customerService.update(id, value) const data = await customerService.decorate( customer, - ["email", "first_name", "last_name", "shipping_addresses"], + ["email", "first_name", "last_name", "shipping_addresses", "phone"], ["orders"] ) res.status(200).json({ customer: data }) diff --git a/packages/medusa/src/models/__mocks__/customer.js b/packages/medusa/src/models/__mocks__/customer.js index c7c8adadfa..7fac374649 100644 --- a/packages/medusa/src/models/__mocks__/customer.js +++ b/packages/medusa/src/models/__mocks__/customer.js @@ -17,6 +17,15 @@ export const customers = { billingAddress: {}, password_hash: "123456789", }, + customerWithPhone: { + _id: IdMap.getId("customerWithPhone"), + email: "oliver@medusa.com", + first_name: "Oliver", + last_name: "Juhl", + billingAddress: {}, + password_hash: "123456789", + phone: "12345678", + }, } export const CustomerModelMock = { @@ -29,6 +38,9 @@ export const CustomerModelMock = { if (query.email === "oliver@medusa.com") { return Promise.resolve(customers.testCustomer) } + if (query.phone === "12345678") { + return Promise.resolve(customers.customerWithPhone) + } if (query._id === IdMap.getId("testCustomer")) { return Promise.resolve(customers.testCustomer) } diff --git a/packages/medusa/src/models/customer.js b/packages/medusa/src/models/customer.js index 6324b6208e..420ebceab3 100644 --- a/packages/medusa/src/models/customer.js +++ b/packages/medusa/src/models/customer.js @@ -17,6 +17,7 @@ class CustomerModel extends BaseModel { payment_methods: { type: [mongoose.Schema.Types.Mixed], default: [] }, shipping_addresses: { type: [AddressSchema], default: [] }, password_hash: { type: String }, + phone: { type: String, default: "" }, has_account: { type: Boolean, default: false }, orders: { type: [String], default: [] }, metadata: { type: mongoose.Schema.Types.Mixed, default: {} }, diff --git a/packages/medusa/src/services/__tests__/customer.js b/packages/medusa/src/services/__tests__/customer.js index db0246556b..11ec79e544 100644 --- a/packages/medusa/src/services/__tests__/customer.js +++ b/packages/medusa/src/services/__tests__/customer.js @@ -48,6 +48,28 @@ describe("CustomerService", () => { }) }) + describe("retrieveByPhone", () => { + let result + beforeAll(async () => { + jest.clearAllMocks() + const customerService = new CustomerService({ + customerModel: CustomerModelMock, + }) + result = await customerService.retrieveByPhone("12345678") + }) + + it("calls customer model functions", () => { + expect(CustomerModelMock.findOne).toHaveBeenCalledTimes(1) + expect(CustomerModelMock.findOne).toHaveBeenCalledWith({ + phone: "12345678", + }) + }) + + it("returns the customer", () => { + expect(result).toEqual(customers.customerWithPhone) + }) + }) + describe("setMetadata", () => { const customerService = new CustomerService({ customerModel: CustomerModelMock, diff --git a/packages/medusa/src/services/customer.js b/packages/medusa/src/services/customer.js index 1950e1b470..216b2d000f 100644 --- a/packages/medusa/src/services/customer.js +++ b/packages/medusa/src/services/customer.js @@ -168,6 +168,26 @@ class CustomerService extends BaseService { return customer } + /** + * Gets a customer by phone. + * @param {string} phone - the phone of the customer to get. + * @return {Promise} the customer document. + */ + async retrieveByPhone(phone) { + const customer = await this.customerModel_.findOne({ phone }).catch(err => { + throw new MedusaError(MedusaError.Types.DB_ERROR, err.message) + }) + + if (!customer) { + throw new MedusaError( + MedusaError.Types.NOT_FOUND, + `Customer with phone ${phone} was not found` + ) + } + + return customer + } + /** * Hashes a password * @param {string} password - the value to hash diff --git a/packages/medusa/yarn.lock b/packages/medusa/yarn.lock index abe6d06477..48d284c5fc 100644 --- a/packages/medusa/yarn.lock +++ b/packages/medusa/yarn.lock @@ -982,16 +982,33 @@ resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== +"@hapi/address@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@hapi/address/-/address-4.1.0.tgz#d60c5c0d930e77456fdcde2598e77302e2955e1d" + integrity sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/formula@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@hapi/formula/-/formula-1.2.0.tgz#994649c7fea1a90b91a0a1e6d983523f680e10cd" integrity sha512-UFbtbGPjstz0eWHb+ga/GM3Z9EzqKXFWIbSOFURU0A/Gku0Bky4bCk9/h//K2Xr3IrCfjFNhMm4jyZ5dbCewGA== +"@hapi/formula@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@hapi/formula/-/formula-2.0.0.tgz#edade0619ed58c8e4f164f233cda70211e787128" + integrity sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A== + "@hapi/hoek@^8.2.4", "@hapi/hoek@^8.3.0": version "8.5.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.0.tgz#2f9ce301c8898e1c3248b0a8564696b24d1a9a5a" integrity sha512-7XYT10CZfPsH7j9F1Jmg1+d0ezOux2oM2GfArAzLwWe4mE2Dr3hVjsAL6+TFY49RRJlCdJDMw3nJsLFroTc8Kw== +"@hapi/hoek@^9.0.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6" + integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw== + "@hapi/joi@^16.1.8": version "16.1.8" resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-16.1.8.tgz#84c1f126269489871ad4e2decc786e0adef06839" @@ -1008,6 +1025,11 @@ resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-1.0.2.tgz#025b7a36dbbf4d35bf1acd071c26b20ef41e0d13" integrity sha512-dtXC/WkZBfC5vxscazuiJ6iq4j9oNx1SHknmIr8hofarpKUZKmlUVYVIhNVzIEgK5Wrc4GMHL5lZtt1uS2flmQ== +"@hapi/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@hapi/pinpoint/-/pinpoint-2.0.0.tgz#805b40d4dbec04fc116a73089494e00f073de8df" + integrity sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw== + "@hapi/topo@^3.1.3": version "3.1.6" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29" @@ -1015,6 +1037,13 @@ dependencies: "@hapi/hoek" "^8.3.0" +"@hapi/topo@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" + integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== + dependencies: + "@hapi/hoek" "^9.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" @@ -4210,6 +4239,17 @@ joi-objectid@^3.0.1: resolved "https://registry.yarnpkg.com/joi-objectid/-/joi-objectid-3.0.1.tgz#63ace7860f8e1a993a28d40c40ffd8eff01a3668" integrity sha512-V/3hbTlGpvJ03Me6DJbdBI08hBTasFOmipsauOsxOSnsF1blxV537WTl1zPwbfcKle4AK0Ma4OPnzMH4LlvTpQ== +joi@^17.2.1: + version "17.2.1" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.2.1.tgz#e5140fdf07e8fecf9bc977c2832d1bdb1e3f2a0a" + integrity sha512-YT3/4Ln+5YRpacdmfEfrrKh50/kkgX3LgBltjqnlMPIYiZ4hxXZuVJcxmsvxsdeHg9soZfE3qXxHC2tMpCCBOA== + dependencies: + "@hapi/address" "^4.1.0" + "@hapi/formula" "^2.0.0" + "@hapi/hoek" "^9.0.0" + "@hapi/pinpoint" "^2.0.0" + "@hapi/topo" "^5.0.0" + js-levenshtein@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -4580,21 +4620,21 @@ 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.0.0-alpha.30: - version "1.0.0-alpha.30" - resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.0.0-alpha.30.tgz#4ff3c1c8202486a8aa14989c8bcca0d981eb4fdc" - integrity sha512-SVcX4/GLm3NntFQzHKALaXi3sQ8PP1eZGXUb6yQEiFnnap0otI37sQCIC+nAw6v14VnGNkoWeVcENti+jSrzVA== +medusa-core-utils@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.0.10.tgz#6175f1e428318205742621f78d387254fc85b8a1" + integrity sha512-z12ITzPl5UpDJTILNXcMGD4yujSRkuvVtxkrvqCmA44IEyRj1hWZ0dGbVzuHj2wIahDHFFg66oq91IQH5QVsyg== dependencies: - "@hapi/joi" "^16.1.8" + joi "^17.2.1" joi-objectid "^3.0.1" -medusa-test-utils@^1.0.0-alpha.30: - version "1.0.0-alpha.30" - resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.0.0-alpha.30.tgz#2a32b5d5d00993d931cd12a5fa42316c01731e41" - integrity sha512-xPPnpLNGSB2eVHxWBRwztPvuIqi6E26QUpRICKzbZ7H3XwsP9G62NTa/TJDrLYmY3232sXeWGZNmOlPZWbQcGw== +medusa-test-utils@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.0.10.tgz#8c1e9046a81cd3afa4c32c6d0d8af7e1f33bd039" + integrity sha512-CTzlVVTEOIFh3iRsjJqt4JYtEFP+2gVZF0jXGYdhCgAxd5mFKVuE+QzLLtvTCHlT7TI7rYgPfEWCcj9LPh2vVQ== dependencies: "@babel/plugin-transform-classes" "^7.9.5" - medusa-core-utils "^1.0.0-alpha.30" + medusa-core-utils "^1.0.10" mongoose "^5.8.0" memory-pager@^1.0.2: