merge develop and resolve conflicts
This commit is contained in:
commit
7cdd628997
151 files changed
+3546
-1239
No files matched your search
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -96,4 +96,33 @@ Joi.orderFilter = () => {
|
||||
})
|
||||
}
|
||||
|
||||
Joi.productFilter = () => {
|
||||
return Joi.object().keys({
|
||||
id: Joi.string(),
|
||||
q: Joi.string().allow(null, ""),
|
||||
status: Joi.array()
|
||||
.items(Joi.string().valid("proposed", "draft", "published", "rejected"))
|
||||
.single(),
|
||||
collection_id: Joi.array()
|
||||
.items(Joi.string())
|
||||
.single(),
|
||||
tags: Joi.array()
|
||||
.items(Joi.string())
|
||||
.single(),
|
||||
title: Joi.string(),
|
||||
description: Joi.string(),
|
||||
handle: Joi.string(),
|
||||
is_giftcard: Joi.string(),
|
||||
type: Joi.string(),
|
||||
offset: Joi.string(),
|
||||
limit: Joi.string(),
|
||||
expand: Joi.string(),
|
||||
fields: Joi.string(),
|
||||
order: Joi.string().optional(),
|
||||
created_at: Joi.dateFilter(),
|
||||
updated_at: Joi.dateFilter(),
|
||||
deleted_at: Joi.dateFilter(),
|
||||
})
|
||||
}
|
||||
|
||||
export default Joi
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# medusa-file-s3
|
||||
|
||||
Upload files to an AWS S3 bucket.
|
||||
|
||||
## Options
|
||||
|
||||
```
|
||||
s3_url: [url of your s3 bucket],
|
||||
access_key_id: [access-key],
|
||||
secret_access_key: [secret-access-key],
|
||||
bucket: [name of your bucket],
|
||||
region: [region of your bucket],
|
||||
```
|
||||
|
||||
Follow [this guide](https://docs.medusa-commerce.com/how-to/uploading-images-to-s3) to configure the plugin.
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# medusa-file-spaces
|
||||
|
||||
Upload files to a DigitalOcean Space.
|
||||
|
||||
## Options
|
||||
|
||||
```
|
||||
spaces_url: [url of your DigitalOcean space],
|
||||
access_key_id: [access-key],
|
||||
secret_access_key: [secret-access-key],
|
||||
bucket: [name of your bucket],
|
||||
endpoint: [endpoint of you DigitalOcean space],
|
||||
```
|
||||
|
||||
Follow [this guide](https://docs.medusa-commerce.com/how-to/uploading-images-to-spaces) to configure the plugin.
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -106,7 +106,13 @@ class WebshipperFulfillmentService extends FulfillmentService {
|
||||
|
||||
const fromOrder = await this.orderService_.retrieve(orderId, {
|
||||
select: ["total"],
|
||||
relations: ["discounts", "shipping_address", "returns"],
|
||||
relations: [
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_address",
|
||||
"returns",
|
||||
],
|
||||
})
|
||||
|
||||
const methodData = returnOrder.shipping_method.data
|
||||
@@ -286,10 +292,11 @@ class WebshipperFulfillmentService extends FulfillmentService {
|
||||
)) &&
|
||||
this.invoiceGenerator_.createCertificateOfOrigin
|
||||
) {
|
||||
const base64Coo = await this.invoiceGenerator_.createCertificateOfOrigin(
|
||||
fromOrder,
|
||||
fulfillmentItems
|
||||
)
|
||||
const base64Coo =
|
||||
await this.invoiceGenerator_.createCertificateOfOrigin(
|
||||
fromOrder,
|
||||
fulfillmentItems
|
||||
)
|
||||
|
||||
certificateOfOrigin = await this.client_.documents
|
||||
.create({
|
||||
@@ -419,9 +426,8 @@ class WebshipperFulfillmentService extends FulfillmentService {
|
||||
url: l.url,
|
||||
tracking_number: l.number,
|
||||
}))
|
||||
const [orderId, fulfillmentIndex] = wsOrder.data.attributes.ext_ref.split(
|
||||
"."
|
||||
)
|
||||
const [orderId, fulfillmentIndex] =
|
||||
wsOrder.data.attributes.ext_ref.split(".")
|
||||
|
||||
if (orderId.charAt(0).toLowerCase() === "s") {
|
||||
if (fulfillmentIndex.startsWith("ful")) {
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
import _ from "lodash"
|
||||
import Stripe from "stripe"
|
||||
import { PaymentService } from "medusa-interfaces"
|
||||
|
||||
class BancontactProviderService extends PaymentService {
|
||||
static identifier = "stripe-bancontact"
|
||||
|
||||
constructor(
|
||||
{ stripeProviderService, customerService, totalsService, regionService },
|
||||
options
|
||||
) {
|
||||
super()
|
||||
|
||||
/**
|
||||
* Required Stripe options:
|
||||
* {
|
||||
* api_key: "stripe_secret_key", REQUIRED
|
||||
* webhook_secret: "stripe_webhook_secret", REQUIRED
|
||||
* // Use this flag to capture payment immediately (default is false)
|
||||
* capture: true
|
||||
* }
|
||||
*/
|
||||
this.options_ = options
|
||||
|
||||
/** @private @const {Stripe} */
|
||||
this.stripe_ = Stripe(options.api_key)
|
||||
|
||||
/** @private @const {CustomerService} */
|
||||
this.stripeProviderService_ = stripeProviderService
|
||||
|
||||
/** @private @const {CustomerService} */
|
||||
this.customerService_ = customerService
|
||||
|
||||
/** @private @const {RegionService} */
|
||||
this.regionService_ = regionService
|
||||
|
||||
/** @private @const {TotalsService} */
|
||||
this.totalsService_ = totalsService
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches Stripe payment intent. Check its status and returns the
|
||||
* corresponding Medusa status.
|
||||
* @param {object} paymentData - payment method data from cart
|
||||
* @returns {string} the status of the payment intent
|
||||
*/
|
||||
async getStatus(paymentData) {
|
||||
return await this.stripeProviderService_.getStatus(paymentData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a customers saved payment methods if registered in Stripe.
|
||||
* @param {object} customer - customer to fetch saved cards for
|
||||
* @returns {Promise<Array<object>>} saved payments methods
|
||||
*/
|
||||
async retrieveSavedMethods(customer) {
|
||||
return Promise.resolve([])
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Stripe customer
|
||||
* @param {string} customerId - Stripe customer id
|
||||
* @returns {Promise<object>} Stripe customer
|
||||
*/
|
||||
async retrieveCustomer(customerId) {
|
||||
return await this.stripeProviderService_.retrieveCustomer(customerId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Stripe customer using a Medusa customer.
|
||||
* @param {object} customer - Customer data from Medusa
|
||||
* @returns {Promise<object>} Stripe customer
|
||||
*/
|
||||
async createCustomer(customer) {
|
||||
return await this.stripeProviderService_.createCustomer(customer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Stripe payment intent.
|
||||
* If customer is not registered in Stripe, we do so.
|
||||
* @param {object} cart - cart to create a payment for
|
||||
* @returns {object} Stripe payment intent
|
||||
*/
|
||||
async createPayment(cart) {
|
||||
const { customer_id, region_id, email } = cart
|
||||
const region = await this.regionService_.retrieve(region_id)
|
||||
const { currency_code } = region
|
||||
|
||||
const amount = await this.totalsService_.getTotal(cart)
|
||||
|
||||
const intentRequest = {
|
||||
amount: Math.round(amount),
|
||||
currency: currency_code,
|
||||
payment_method_types: ["bancontact"],
|
||||
capture_method: "automatic",
|
||||
metadata: { cart_id: `${cart.id}` },
|
||||
}
|
||||
|
||||
if (customer_id) {
|
||||
const customer = await this.customerService_.retrieve(customer_id)
|
||||
|
||||
if (customer.metadata?.stripe_id) {
|
||||
intentRequest.customer = customer.metadata.stripe_id
|
||||
} else {
|
||||
const stripeCustomer = await this.createCustomer({
|
||||
email,
|
||||
id: customer_id,
|
||||
})
|
||||
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
} else {
|
||||
const stripeCustomer = await this.createCustomer({
|
||||
email,
|
||||
})
|
||||
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
|
||||
const paymentIntent = await this.stripe_.paymentIntents.create(
|
||||
intentRequest
|
||||
)
|
||||
|
||||
return paymentIntent
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves Stripe payment intent.
|
||||
* @param {object} data - the data of the payment to retrieve
|
||||
* @returns {Promise<object>} Stripe payment intent
|
||||
*/
|
||||
async retrievePayment(data) {
|
||||
return await this.stripeProviderService_.retrievePayment(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Stripe payment intent and returns it.
|
||||
* @param {object} sessionData - the data of the payment to retrieve
|
||||
* @returns {Promise<object>} Stripe payment intent
|
||||
*/
|
||||
async getPaymentData(sessionData) {
|
||||
return await this.stripeProviderService_.getPaymentData(sessionData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorizes Stripe payment intent by simply returning
|
||||
* the status for the payment intent in use.
|
||||
* @param {object} sessionData - payment session data
|
||||
* @param {object} context - properties relevant to current context
|
||||
* @returns {Promise<{ status: string, data: object }>} result with data and status
|
||||
*/
|
||||
async authorizePayment(sessionData, context = {}) {
|
||||
return await this.stripeProviderService_.authorizePayment(
|
||||
sessionData,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
async updatePaymentData(sessionData, update) {
|
||||
return await this.stripeProviderService_.updatePaymentData(
|
||||
sessionData,
|
||||
update
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates Stripe payment intent.
|
||||
* @param {object} sessionData - payment session data.
|
||||
* @param {object} update - objec to update intent with
|
||||
* @returns {object} Stripe payment intent
|
||||
*/
|
||||
async updatePayment(sessionData, cart) {
|
||||
try {
|
||||
const stripeId = cart.customer?.metadata?.stripe_id || undefined
|
||||
|
||||
if (stripeId !== sessionData.customer) {
|
||||
return this.createPayment(cart)
|
||||
} else {
|
||||
if (cart.total && sessionData.amount === Math.round(cart.total)) {
|
||||
return sessionData
|
||||
}
|
||||
|
||||
return this.stripe_.paymentIntents.update(sessionData.id, {
|
||||
amount: Math.round(cart.total),
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async deletePayment(payment) {
|
||||
return await this.stripeProviderService_.deletePayment(payment)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates customer of Stripe payment intent.
|
||||
* @param {string} paymentIntentId - id of payment intent to update
|
||||
* @param {string} customerId - id of new Stripe customer
|
||||
* @returns {object} Stripe payment intent
|
||||
*/
|
||||
async updatePaymentIntentCustomer(paymentIntentId, customerId) {
|
||||
return await this.stripeProviderService_.updatePaymentIntentCustomer(
|
||||
paymentIntentId,
|
||||
customerId
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures payment for Stripe payment intent.
|
||||
* @param {object} paymentData - payment method data from cart
|
||||
* @returns {object} Stripe payment intent
|
||||
*/
|
||||
async capturePayment(payment) {
|
||||
return await this.stripeProviderService_.capturePayment(payment)
|
||||
}
|
||||
|
||||
/**
|
||||
* Refunds payment for Stripe payment intent.
|
||||
* @param {object} paymentData - payment method data from cart
|
||||
* @param {number} amountToRefund - amount to refund
|
||||
* @returns {string} refunded payment intent
|
||||
*/
|
||||
async refundPayment(payment, amountToRefund) {
|
||||
return await this.stripeProviderService_.refundPayment(
|
||||
payment,
|
||||
amountToRefund
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels payment for Stripe payment intent.
|
||||
* @param {object} paymentData - payment method data from cart
|
||||
* @returns {object} canceled payment intent
|
||||
*/
|
||||
async cancelPayment(payment) {
|
||||
return await this.stripeProviderService_.cancelPayment(payment)
|
||||
}
|
||||
}
|
||||
|
||||
export default BancontactProviderService
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
+56
-5
@@ -135,6 +135,57 @@ describe("RestockNotificationService", () => {
|
||||
})
|
||||
|
||||
describe("triggerRestock", () => {
|
||||
afterEach(() => {
|
||||
jest.useRealTimers()
|
||||
})
|
||||
|
||||
it("trigger delay default to 0", async () => {
|
||||
const restockNotiService = new RestockNotificationService({
|
||||
manager: MockManager,
|
||||
productVariantService: ProductVariantService,
|
||||
restockNotificationModel: RestockNotificationModel,
|
||||
eventBusService: EventBusService,
|
||||
})
|
||||
|
||||
restockNotiService.restockExecute_ = jest.fn()
|
||||
|
||||
jest.clearAllMocks()
|
||||
jest.useFakeTimers()
|
||||
|
||||
restockNotiService.triggerRestock("variant_test")
|
||||
|
||||
jest.runAllTimers()
|
||||
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1)
|
||||
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 0)
|
||||
})
|
||||
|
||||
it("trigger delay 10", async () => {
|
||||
const restockNotiService = new RestockNotificationService(
|
||||
{
|
||||
manager: MockManager,
|
||||
productVariantService: ProductVariantService,
|
||||
restockNotificationModel: RestockNotificationModel,
|
||||
eventBusService: EventBusService,
|
||||
},
|
||||
{ trigger_delay: 10 }
|
||||
)
|
||||
|
||||
restockNotiService.restockExecute_ = jest.fn()
|
||||
|
||||
jest.clearAllMocks()
|
||||
jest.useFakeTimers()
|
||||
|
||||
restockNotiService.triggerRestock("variant_test")
|
||||
|
||||
jest.runAllTimers()
|
||||
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1)
|
||||
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 10)
|
||||
})
|
||||
})
|
||||
|
||||
describe("restockExecute_", () => {
|
||||
const restockNotiService = new RestockNotificationService({
|
||||
manager: MockManager,
|
||||
productVariantService: ProductVariantService,
|
||||
@@ -145,20 +196,20 @@ describe("RestockNotificationService", () => {
|
||||
it("non-existing noti does nothing", async () => {
|
||||
jest.clearAllMocks()
|
||||
|
||||
await expect(restockNotiService.triggerRestock("variant_test")).resolves
|
||||
await expect(restockNotiService.restockExecute_("variant_test")).resolves
|
||||
})
|
||||
|
||||
it("existing noti but out of stock does nothing", async () => {
|
||||
jest.clearAllMocks()
|
||||
|
||||
await expect(restockNotiService.triggerRestock("variant_outofstock"))
|
||||
await expect(restockNotiService.restockExecute_("variant_outofstock"))
|
||||
.resolves
|
||||
})
|
||||
|
||||
it("existing noti emits and deletes", async () => {
|
||||
jest.clearAllMocks()
|
||||
|
||||
await restockNotiService.triggerRestock("variant_1234")
|
||||
await restockNotiService.restockExecute_("variant_1234")
|
||||
|
||||
expect(EventBusService.emit).toHaveBeenCalledTimes(1)
|
||||
expect(EventBusService.emit).toHaveBeenCalledWith(
|
||||
@@ -187,7 +238,7 @@ describe("RestockNotificationService", () => {
|
||||
{ inventory_required: 5 }
|
||||
)
|
||||
|
||||
await service.triggerRestock("variant_1234")
|
||||
await service.restockExecute_("variant_1234")
|
||||
|
||||
expect(EventBusService.emit).toHaveBeenCalledTimes(1)
|
||||
expect(EventBusService.emit).toHaveBeenCalledWith(
|
||||
@@ -214,7 +265,7 @@ describe("RestockNotificationService", () => {
|
||||
{ inventory_required: 5 }
|
||||
)
|
||||
|
||||
await service.triggerRestock("variant_low_inventory")
|
||||
await service.restockExecute_("variant_low_inventory")
|
||||
|
||||
expect(EventBusService.emit).toHaveBeenCalledTimes(0)
|
||||
expect(RestockNotificationModel.delete).toHaveBeenCalledTimes(0)
|
||||
|
||||
@@ -108,10 +108,15 @@ class RestockNotificationService extends BaseService {
|
||||
* and emits a restocked event to the event bus. After successful emission the
|
||||
* restock notification is deleted.
|
||||
* @param {string} variantId - the variant id to trigger restock for
|
||||
* @return {Promise<RestockNotification>} The resulting restock notification
|
||||
* @return The resulting restock notification
|
||||
*/
|
||||
async triggerRestock(variantId) {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
triggerRestock(variantId) {
|
||||
const delay = this.options_?.trigger_delay ?? 0
|
||||
setTimeout(() => this.restockExecute_(variantId), delay)
|
||||
}
|
||||
|
||||
async restockExecute_(variantId) {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const restockRepo = manager.getRepository(this.restockNotificationModel_)
|
||||
|
||||
const existing = await this.retrieve(variantId)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -44,6 +44,8 @@ class OrderSubscriber {
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
@@ -146,6 +148,8 @@ class OrderSubscriber {
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
@@ -253,6 +257,8 @@ class OrderSubscriber {
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -320,6 +320,8 @@ class SendGridService extends NotificationService {
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"shipping_methods.shipping_option",
|
||||
"payments",
|
||||
@@ -363,6 +365,8 @@ class SendGridService extends NotificationService {
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"shipping_methods.shipping_option",
|
||||
"payments",
|
||||
@@ -496,6 +500,8 @@ class SendGridService extends NotificationService {
|
||||
relations: [
|
||||
"items",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_address",
|
||||
"returns",
|
||||
"swaps",
|
||||
@@ -601,6 +607,8 @@ class SendGridService extends NotificationService {
|
||||
relations: [
|
||||
"items",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_address",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
@@ -686,7 +694,14 @@ class SendGridService extends NotificationService {
|
||||
})
|
||||
|
||||
const order = await this.orderService_.retrieve(swap.order_id, {
|
||||
relations: ["items", "discounts", "swaps", "swaps.additional_items"],
|
||||
relations: [
|
||||
"items",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
],
|
||||
})
|
||||
|
||||
let merged = [...order.items]
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -40,6 +40,8 @@ class SlackService extends BaseService {
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import _ from "lodash"
|
||||
|
||||
/**
|
||||
* @oas [get] /auth
|
||||
* operationId: "DeleteAuth"
|
||||
* summary: "Delete Session"
|
||||
* description: "Deletes the current session for the logged in user."
|
||||
* tags:
|
||||
* - Auth
|
||||
* responses:
|
||||
* "200":
|
||||
* description: OK
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
req.session.destroy()
|
||||
res.status(200).end()
|
||||
}
|
||||
@@ -13,5 +13,11 @@ export default app => {
|
||||
)
|
||||
route.post("/", middlewares.wrap(require("./create-session").default))
|
||||
|
||||
route.delete(
|
||||
"/",
|
||||
middlewares.authenticate(),
|
||||
middlewares.wrap(require("./delete-session").default)
|
||||
)
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultRelations } from "."
|
||||
|
||||
/**
|
||||
* @oas [post] /discounts
|
||||
@@ -96,11 +97,10 @@ export default async (req, res) => {
|
||||
const discountService = req.scope.resolve("discountService")
|
||||
|
||||
const created = await discountService.create(value)
|
||||
const discount = await discountService.retrieve(created.id, [
|
||||
"rule",
|
||||
"rule.valid_for",
|
||||
"regions",
|
||||
])
|
||||
const discount = await discountService.retrieve(
|
||||
created.id,
|
||||
defaultRelations
|
||||
)
|
||||
|
||||
res.status(200).json({ discount })
|
||||
} catch (err) {
|
||||
|
||||
@@ -57,6 +57,7 @@ export const defaultCartRelations = [
|
||||
"payment_sessions",
|
||||
"shipping_methods.shipping_option",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
]
|
||||
|
||||
export const defaultCartFields = [
|
||||
|
||||
@@ -43,7 +43,14 @@ export default async (req, res) => {
|
||||
.withTransaction(manager)
|
||||
.retrieve(draftOrder.cart_id, {
|
||||
select: ["total"],
|
||||
relations: ["discounts", "shipping_methods", "region", "items"],
|
||||
relations: [
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"region",
|
||||
"items",
|
||||
],
|
||||
})
|
||||
|
||||
await paymentProviderService
|
||||
|
||||
@@ -7,6 +7,8 @@ const defaultRelations = [
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
|
||||
@@ -202,7 +202,12 @@ export default async (req, res) => {
|
||||
const order = await orderService
|
||||
.withTransaction(manager)
|
||||
.retrieve(id, {
|
||||
relations: ["items", "discounts"],
|
||||
relations: [
|
||||
"items",
|
||||
"cart",
|
||||
"cart.discounts",
|
||||
"cart.discounts.rule",
|
||||
],
|
||||
})
|
||||
|
||||
await claimService.withTransaction(manager).create({
|
||||
|
||||
@@ -221,6 +221,8 @@ export const defaultRelations = [
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
@@ -316,6 +318,8 @@ export const allowedRelations = [
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
|
||||
@@ -46,7 +46,11 @@ export default app => {
|
||||
)
|
||||
|
||||
route.get("/:id", middlewares.wrap(require("./get-product").default))
|
||||
route.get("/", middlewares.wrap(require("./list-products").default))
|
||||
route.get(
|
||||
"/",
|
||||
middlewares.normalizeQuery(),
|
||||
middlewares.wrap(require("./list-products").default)
|
||||
)
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -121,3 +125,18 @@ export const allowedRelations = [
|
||||
"type",
|
||||
"collection",
|
||||
]
|
||||
|
||||
export const filterableFields = [
|
||||
"id",
|
||||
"status",
|
||||
"collection_id",
|
||||
"tags",
|
||||
"title",
|
||||
"description",
|
||||
"handle",
|
||||
"is_giftcard",
|
||||
"type",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
import _ from "lodash"
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultFields, defaultRelations } from "./"
|
||||
import { defaultFields, defaultRelations, filterableFields } from "./"
|
||||
|
||||
/**
|
||||
* @oas [get] /products
|
||||
@@ -31,6 +31,17 @@ import { defaultFields, defaultRelations } from "./"
|
||||
* $ref: "#/components/schemas/product"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.productFilter()
|
||||
|
||||
const { value, error } = schema.validate(req.query)
|
||||
|
||||
if (error) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
JSON.stringify(error.details)
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
const productService = req.scope.resolve("productService")
|
||||
|
||||
@@ -53,21 +64,16 @@ export default async (req, res) => {
|
||||
expandFields = req.query.expand.split(",")
|
||||
}
|
||||
|
||||
if ("is_giftcard" in req.query) {
|
||||
selector.is_giftcard = req.query.is_giftcard === "true"
|
||||
for (const k of filterableFields) {
|
||||
if (k in value) {
|
||||
selector[k] = value[k]
|
||||
}
|
||||
}
|
||||
|
||||
if ("status" in req.query) {
|
||||
const schema = Validator.array()
|
||||
.items(
|
||||
Validator.string().valid("proposed", "draft", "published", "rejected")
|
||||
)
|
||||
.single()
|
||||
|
||||
const { value, error } = schema.validate(req.query.status)
|
||||
|
||||
if (value && !error) {
|
||||
selector.status = value
|
||||
if (selector.status?.indexOf("null") > -1) {
|
||||
selector.status.splice(selector.status.indexOf("null"), 1)
|
||||
if (selector.status.length === 0) {
|
||||
delete selector.status
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,14 @@ export default async (req, res) => {
|
||||
if (!value.region_id) {
|
||||
const regionService = req.scope.resolve("regionService")
|
||||
const regions = await regionService.withTransaction(manager).list({})
|
||||
|
||||
if (!regions?.length) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`A region is required to create a cart`
|
||||
)
|
||||
}
|
||||
|
||||
regionId = regions[0].id
|
||||
}
|
||||
|
||||
|
||||
@@ -116,4 +116,6 @@ export const defaultRelations = [
|
||||
"payment_sessions",
|
||||
"shipping_methods.shipping_option",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
]
|
||||
@@ -36,6 +36,8 @@ export const defaultRelations = [
|
||||
"items.variant.product",
|
||||
"shipping_methods",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"customer",
|
||||
"payments",
|
||||
"region",
|
||||
@@ -74,6 +76,8 @@ export const allowedRelations = [
|
||||
"items.variant.product",
|
||||
"shipping_methods",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"customer",
|
||||
"payments",
|
||||
"region",
|
||||
|
||||
@@ -16,7 +16,7 @@ describe("Get variant by id", () => {
|
||||
it("calls get variant from variantSerice", () => {
|
||||
expect(ProductVariantServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||
expect(ProductVariantServiceMock.retrieve).toHaveBeenCalledWith("1", {
|
||||
relations: ["prices"],
|
||||
relations: ["prices", "options"],
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -12,4 +12,4 @@ export default app => {
|
||||
return app
|
||||
}
|
||||
|
||||
export const defaultRelations = ["prices"]
|
||||
export const defaultRelations = ["prices", "options"]
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
|
||||
export class deleteDateOnShippingOptionRequirements1632828114899
|
||||
implements MigrationInterface {
|
||||
name = "deleteDateOnShippingOptionRequirements1632828114899"
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "shipping_option_requirement" ADD "deleted_at" TIMESTAMP WITH TIME ZONE`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "shipping_option_requirement" DROP COLUMN "deleted_at"`
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export class Discount {
|
||||
@Column({ nullable: true })
|
||||
rule_id: string
|
||||
|
||||
@ManyToOne(() => DiscountRule, { cascade: true, eager: true })
|
||||
@ManyToOne(() => DiscountRule, { cascade: true })
|
||||
@JoinColumn({ name: "rule_id" })
|
||||
rule: DiscountRule
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
JoinTable,
|
||||
} from "typeorm"
|
||||
import { ulid } from "ulid"
|
||||
import { DbAwareColumn } from "../utils/db-aware-column"
|
||||
import { DbAwareColumn, resolveDbType } from "../utils/db-aware-column"
|
||||
|
||||
import { ShippingOption } from "./shipping-option"
|
||||
|
||||
@@ -44,6 +44,9 @@ export class ShippingOptionRequirement {
|
||||
@Column({ type: "int" })
|
||||
amount: number
|
||||
|
||||
@DeleteDateColumn({ type: resolveDbType("timestamptz") })
|
||||
deleted_at: Date
|
||||
|
||||
@BeforeInsert()
|
||||
private beforeInsert() {
|
||||
if (this.id) return
|
||||
|
||||
@@ -15,7 +15,27 @@ export class ProductRepository extends Repository<Product> {
|
||||
if (Array.isArray(idsOrOptionsWithoutRelations)) {
|
||||
entities = await this.findByIds(idsOrOptionsWithoutRelations)
|
||||
} else {
|
||||
entities = await this.find(idsOrOptionsWithoutRelations)
|
||||
// Since tags are in a one-to-many realtion they cant be included in a
|
||||
// regular query, to solve this add the join on tags seperately if
|
||||
// the query exists
|
||||
const tags = idsOrOptionsWithoutRelations.where.tags
|
||||
delete idsOrOptionsWithoutRelations.where.tags
|
||||
let qb = this.createQueryBuilder("product")
|
||||
.select(["product.id"])
|
||||
.where(idsOrOptionsWithoutRelations.where)
|
||||
.skip(idsOrOptionsWithoutRelations.skip)
|
||||
.take(idsOrOptionsWithoutRelations.take)
|
||||
|
||||
if (tags) {
|
||||
qb = qb
|
||||
.leftJoinAndSelect("product.tags", "tags")
|
||||
.andWhere(
|
||||
`tags.id IN (:...ids)`, { ids: tags._value}
|
||||
)
|
||||
}
|
||||
|
||||
entities = await qb
|
||||
.getMany()
|
||||
}
|
||||
const entitiesIds = entities.map(({ id }) => id)
|
||||
|
||||
|
||||
@@ -647,12 +647,13 @@ describe("CartService", () => {
|
||||
"shipping_address",
|
||||
"billing_address",
|
||||
"gift_cards",
|
||||
"discounts",
|
||||
"customer",
|
||||
"region",
|
||||
"payment_sessions",
|
||||
"region.countries",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"discounts.regions",
|
||||
],
|
||||
{
|
||||
|
||||
@@ -13,6 +13,9 @@ describe("DiscountService", () => {
|
||||
id: IdMap.getId("france"),
|
||||
}
|
||||
},
|
||||
withTransaction: function() {
|
||||
return this
|
||||
},
|
||||
}
|
||||
|
||||
const discountService = new DiscountService({
|
||||
|
||||
@@ -231,6 +231,8 @@ describe("OrderService", () => {
|
||||
"payment",
|
||||
"items",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"gift_cards",
|
||||
"shipping_methods",
|
||||
],
|
||||
|
||||
@@ -296,24 +296,19 @@ describe("ShippingOptionService", () => {
|
||||
})
|
||||
|
||||
describe("removeRequirement", () => {
|
||||
const shippingOptionRepository = MockRepository({
|
||||
findOne: q => {
|
||||
switch (q.where.id) {
|
||||
default:
|
||||
return Promise.resolve({
|
||||
requirements: [
|
||||
{
|
||||
id: IdMap.getId("requirement_id"),
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
const shippingOptionRequirementRepository = MockRepository({
|
||||
softRemove: q => {
|
||||
return Promise.resolve()
|
||||
},
|
||||
findOne: i =>
|
||||
i.where.id === IdMap.getId("requirement_id")
|
||||
? { id: IdMap.getId("requirement_id") }
|
||||
: null,
|
||||
})
|
||||
|
||||
const optionService = new ShippingOptionService({
|
||||
manager: MockManager,
|
||||
shippingOptionRepository,
|
||||
shippingOptionRequirementRepository,
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -321,22 +316,19 @@ describe("ShippingOptionService", () => {
|
||||
})
|
||||
|
||||
it("remove requirement successfully", async () => {
|
||||
await optionService.removeRequirement(
|
||||
IdMap.getId("validId"),
|
||||
IdMap.getId("requirement_id")
|
||||
)
|
||||
await optionService.removeRequirement(IdMap.getId("requirement_id"))
|
||||
|
||||
expect(shippingOptionRepository.save).toBeCalledTimes(1)
|
||||
expect(shippingOptionRepository.save).toBeCalledWith({ requirements: [] })
|
||||
expect(shippingOptionRequirementRepository.findOne).toBeCalledTimes(1)
|
||||
expect(shippingOptionRequirementRepository.findOne).toBeCalledWith({
|
||||
where: { id: IdMap.getId("requirement_id") },
|
||||
})
|
||||
expect(shippingOptionRequirementRepository.softRemove).toBeCalledTimes(1)
|
||||
})
|
||||
|
||||
it("is idempotent", async () => {
|
||||
await optionService.removeRequirement(IdMap.getId("validId"), "something")
|
||||
|
||||
expect(shippingOptionRepository.save).toBeCalledTimes(1)
|
||||
expect(shippingOptionRepository.save).toBeCalledWith({
|
||||
requirements: [{ id: IdMap.getId("requirement_id") }],
|
||||
})
|
||||
expect(shippingOptionRequirementRepository.softRemove).toBeCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ describe("SwapService", () => {
|
||||
"order.swaps",
|
||||
"order.swaps.additional_items",
|
||||
"order.discounts",
|
||||
"order.discounts.rule",
|
||||
"additional_items",
|
||||
"return_order",
|
||||
"return_order.items",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { BaseService } from "medusa-interfaces"
|
||||
|
||||
/**
|
||||
* Can authenticate a user based on email password combination
|
||||
* @implements BaseService
|
||||
* @extends BaseService
|
||||
*/
|
||||
class AuthService extends BaseService {
|
||||
constructor({ userService, customerService }) {
|
||||
@@ -47,7 +47,9 @@ class AuthService extends BaseService {
|
||||
success: true,
|
||||
user,
|
||||
}
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -166,6 +166,8 @@ class CartService extends BaseService {
|
||||
relationSet.add("items")
|
||||
relationSet.add("gift_cards")
|
||||
relationSet.add("discounts")
|
||||
relationSet.add("discounts.rule")
|
||||
relationSet.add("discounts.rule.valid_for")
|
||||
//relationSet.add("discounts.parent_discount")
|
||||
//relationSet.add("discounts.parent_discount.rule")
|
||||
//relationSet.add("discounts.parent_discount.regions")
|
||||
@@ -600,18 +602,21 @@ class CartService extends BaseService {
|
||||
"shipping_address",
|
||||
"billing_address",
|
||||
"gift_cards",
|
||||
"discounts",
|
||||
"customer",
|
||||
"region",
|
||||
"payment_sessions",
|
||||
"region.countries",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"discounts.regions",
|
||||
],
|
||||
})
|
||||
|
||||
if ("region_id" in update) {
|
||||
await this.setRegion_(cart, update.region_id, update.country_code)
|
||||
const countryCode =
|
||||
update.country_code || update.shipping_address?.country_code
|
||||
await this.setRegion_(cart, update.region_id, countryCode)
|
||||
}
|
||||
|
||||
if ("customer_id" in update) {
|
||||
@@ -871,6 +876,7 @@ class CartService extends BaseService {
|
||||
async applyDiscount(cart, discountCode) {
|
||||
const discount = await this.discountService_.retrieveByCode(discountCode, [
|
||||
"rule",
|
||||
"rule.valid_for",
|
||||
"regions",
|
||||
])
|
||||
|
||||
@@ -968,7 +974,13 @@ class CartService extends BaseService {
|
||||
async removeDiscount(cartId, discountCode) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
const cart = await this.retrieve(cartId, {
|
||||
relations: ["discounts", "payment_sessions", "shipping_methods"],
|
||||
relations: [
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"payment_sessions",
|
||||
"shipping_methods",
|
||||
],
|
||||
})
|
||||
|
||||
if (cart.discounts.some(({ rule }) => rule.type === "free_shipping")) {
|
||||
@@ -1165,6 +1177,8 @@ class CartService extends BaseService {
|
||||
relations: [
|
||||
"items",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"gift_cards",
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
@@ -1317,6 +1331,8 @@ class CartService extends BaseService {
|
||||
relations: [
|
||||
"shipping_methods",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods.shipping_option",
|
||||
"items",
|
||||
"items.variant",
|
||||
@@ -1369,7 +1385,12 @@ class CartService extends BaseService {
|
||||
}
|
||||
|
||||
const result = await this.retrieve(cartId, {
|
||||
relations: ["discounts", "shipping_methods"],
|
||||
relations: [
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
],
|
||||
})
|
||||
|
||||
// if cart has freeshipping, adjust price
|
||||
@@ -1546,7 +1567,13 @@ class CartService extends BaseService {
|
||||
async delete(cartId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
const cart = await this.retrieve(cartId, {
|
||||
relations: ["items", "discounts", "payment_sessions"],
|
||||
relations: [
|
||||
"items",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"payment_sessions",
|
||||
],
|
||||
})
|
||||
|
||||
if (cart.completed_at) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import _ from "lodash"
|
||||
import { Validator, MedusaError } from "medusa-core-utils"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
import { Brackets } from "typeorm"
|
||||
|
||||
class ClaimService extends BaseService {
|
||||
static Events = {
|
||||
@@ -102,7 +100,7 @@ class ClaimService extends BaseService {
|
||||
}
|
||||
|
||||
update(id, data) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const claimRepo = manager.getCustomRepository(this.claimRepository_)
|
||||
const claim = await this.retrieve(id, { relations: ["shipping_methods"] })
|
||||
|
||||
@@ -113,13 +111,7 @@ class ClaimService extends BaseService {
|
||||
)
|
||||
}
|
||||
|
||||
const {
|
||||
claim_items,
|
||||
shipping_methods,
|
||||
metadata,
|
||||
fulfillment_status,
|
||||
no_notification,
|
||||
} = data
|
||||
const { claim_items, shipping_methods, metadata, no_notification } = data
|
||||
|
||||
if (metadata) {
|
||||
claim.metadata = this.setMetadata_(claim, metadata)
|
||||
@@ -183,9 +175,11 @@ class ClaimService extends BaseService {
|
||||
* Creates a Claim on an Order. Claims consists of items that are claimed and
|
||||
* optionally items to be sent as replacement for the claimed items. The
|
||||
* shipping address that the new items will be shipped to
|
||||
* @param {Object} data - the object containing all data required to create a claim
|
||||
* @return {Object} created claim
|
||||
*/
|
||||
create(data) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const claimRepo = manager.getCustomRepository(this.claimRepository_)
|
||||
|
||||
const {
|
||||
@@ -257,8 +251,8 @@ class ClaimService extends BaseService {
|
||||
|
||||
let toRefund = refund_amount
|
||||
if (type === "refund" && typeof refund_amount === "undefined") {
|
||||
const lines = claim_items.map(ci => {
|
||||
const orderItem = order.items.find(oi => oi.id === ci.item_id)
|
||||
const lines = claim_items.map((ci) => {
|
||||
const orderItem = order.items.find((oi) => oi.id === ci.item_id)
|
||||
return {
|
||||
...orderItem,
|
||||
quantity: ci.quantity,
|
||||
@@ -274,7 +268,7 @@ class ClaimService extends BaseService {
|
||||
}
|
||||
|
||||
const newItems = await Promise.all(
|
||||
additional_items.map(i =>
|
||||
additional_items.map((i) =>
|
||||
this.lineItemService_
|
||||
.withTransaction(manager)
|
||||
.generate(i.variant_id, order.region_id, i.quantity)
|
||||
@@ -332,7 +326,7 @@ class ClaimService extends BaseService {
|
||||
await this.returnService_.withTransaction(manager).create({
|
||||
order_id: order.id,
|
||||
claim_order_id: result.id,
|
||||
items: claim_items.map(ci => ({
|
||||
items: claim_items.map((ci) => ({
|
||||
item_id: ci.item_id,
|
||||
quantity: ci.quantity,
|
||||
metadata: ci.metadata,
|
||||
@@ -362,7 +356,7 @@ class ClaimService extends BaseService {
|
||||
) {
|
||||
const { metadata, no_notification } = config
|
||||
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const claim = await this.retrieve(id, {
|
||||
relations: [
|
||||
"additional_items",
|
||||
@@ -429,7 +423,7 @@ class ClaimService extends BaseService {
|
||||
is_claim: true,
|
||||
no_notification: evaluatedNoNotification,
|
||||
},
|
||||
claim.additional_items.map(i => ({
|
||||
claim.additional_items.map((i) => ({
|
||||
item_id: i.id,
|
||||
quantity: i.quantity,
|
||||
})),
|
||||
@@ -445,7 +439,7 @@ class ClaimService extends BaseService {
|
||||
|
||||
for (const item of claim.additional_items) {
|
||||
const fulfillmentItem = successfullyFulfilled.find(
|
||||
f => item.id === f.item_id
|
||||
(f) => item.id === f.item_id
|
||||
)
|
||||
|
||||
if (fulfillmentItem) {
|
||||
@@ -485,7 +479,7 @@ class ClaimService extends BaseService {
|
||||
}
|
||||
|
||||
async cancelFulfillment(fulfillmentId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const canceled = await this.fulfillmentService_
|
||||
.withTransaction(manager)
|
||||
.cancelFulfillment(fulfillmentId)
|
||||
@@ -508,7 +502,7 @@ class ClaimService extends BaseService {
|
||||
}
|
||||
|
||||
async processRefund(id) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const claim = await this.retrieve(id, {
|
||||
relations: ["order", "order.payments"],
|
||||
})
|
||||
@@ -560,7 +554,7 @@ class ClaimService extends BaseService {
|
||||
) {
|
||||
const { metadata, no_notification } = config
|
||||
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const claim = await this.retrieve(id, {
|
||||
relations: ["additional_items"],
|
||||
})
|
||||
@@ -584,7 +578,7 @@ class ClaimService extends BaseService {
|
||||
claim.fulfillment_status = "shipped"
|
||||
|
||||
for (const i of claim.additional_items) {
|
||||
const shipped = shipment.items.find(si => si.item_id === i.id)
|
||||
const shipped = shipment.items.find((si) => si.item_id === i.id)
|
||||
if (shipped) {
|
||||
const shippedQty = (i.shipped_quantity || 0) + shipped.quantity
|
||||
await this.lineItemService_.withTransaction(manager).update(i.id, {
|
||||
@@ -617,7 +611,7 @@ class ClaimService extends BaseService {
|
||||
}
|
||||
|
||||
async cancel(id) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const claim = await this.retrieve(id, {
|
||||
relations: ["return_order", "fulfillments", "order", "order.refunds"],
|
||||
})
|
||||
@@ -665,6 +659,7 @@ class ClaimService extends BaseService {
|
||||
|
||||
/**
|
||||
* @param {Object} selector - the query object for find
|
||||
* @param {Object} config - the config object containing query settings
|
||||
* @return {Promise} the result of the find operation
|
||||
*/
|
||||
async list(
|
||||
@@ -678,7 +673,8 @@ class ClaimService extends BaseService {
|
||||
|
||||
/**
|
||||
* Gets an order by id.
|
||||
* @param {string} orderId - id of order to retrieve
|
||||
* @param {string} claimId - id of order to retrieve
|
||||
* @param {Object} config - the config object containing query settings
|
||||
* @return {Promise<Order>} the order document
|
||||
*/
|
||||
async retrieve(claimId, config = {}) {
|
||||
@@ -717,7 +713,7 @@ class ClaimService extends BaseService {
|
||||
const keyPath = `metadata.${key}`
|
||||
return this.orderModel_
|
||||
.updateOne({ _id: validatedId }, { $unset: { [keyPath]: "" } })
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
import _ from "lodash"
|
||||
|
||||
class CustomShippingOptionService extends BaseService {
|
||||
constructor({ manager, customShippingOptionRepository }) {
|
||||
@@ -36,7 +35,7 @@ class CustomShippingOptionService extends BaseService {
|
||||
* Retrieves a specific shipping option.
|
||||
* @param {string} id - the id of the custom shipping option to retrieve.
|
||||
* @param {*} config - any options needed to query for the result.
|
||||
* @returns {Promise} which resolves to the requested custom shipping option.
|
||||
* @return {Promise} which resolves to the requested custom shipping option.
|
||||
*/
|
||||
async retrieve(id, config = {}) {
|
||||
const customShippingOptionRepo = this.manager_.getCustomRepository(
|
||||
@@ -84,14 +83,14 @@ class CustomShippingOptionService extends BaseService {
|
||||
* Creates a custom shipping option associated with a given author
|
||||
* @param {object} data - the custom shipping option to create
|
||||
* @param {*} config - any configurations if needed, including meta data
|
||||
* @returns {Promise} resolves to the creation result
|
||||
* @return {Promise} resolves to the creation result
|
||||
*/
|
||||
async create(data, config = { metadata: {} }) {
|
||||
const { metadata } = config
|
||||
|
||||
const { cart_id, shipping_option_id, price } = data
|
||||
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const customShippingOptionRepo = manager.getCustomRepository(
|
||||
this.customShippingOptionRepository_
|
||||
)
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import _ from "lodash"
|
||||
import randomize from "randomatic"
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
import { Validator, MedusaError } from "medusa-core-utils"
|
||||
import { MedusaErrorCodes } from "medusa-core-utils/dist/errors"
|
||||
import { parse, toSeconds } from "iso8601-duration"
|
||||
import { Brackets, ILike } from "typeorm"
|
||||
|
||||
/**
|
||||
* Provides layer to manipulate discounts.
|
||||
* @implements BaseService
|
||||
* @implements {BaseService}
|
||||
*/
|
||||
class DiscountService extends BaseService {
|
||||
constructor({
|
||||
@@ -17,7 +14,6 @@ class DiscountService extends BaseService {
|
||||
discountRuleRepository,
|
||||
giftCardRepository,
|
||||
totalsService,
|
||||
productVariantService,
|
||||
productService,
|
||||
regionService,
|
||||
eventBusService,
|
||||
@@ -80,21 +76,13 @@ class DiscountService extends BaseService {
|
||||
id: Validator.string().optional(),
|
||||
description: Validator.string().optional(),
|
||||
type: Validator.string().required(),
|
||||
value: Validator.number()
|
||||
.min(0)
|
||||
.required(),
|
||||
value: Validator.number().min(0).required(),
|
||||
allocation: Validator.string().required(),
|
||||
valid_for: Validator.array().optional(),
|
||||
created_at: Validator.date().optional(),
|
||||
updated_at: Validator.date()
|
||||
.allow(null)
|
||||
.optional(),
|
||||
deleted_at: Validator.date()
|
||||
.allow(null)
|
||||
.optional(),
|
||||
metadata: Validator.object()
|
||||
.allow(null)
|
||||
.optional(),
|
||||
updated_at: Validator.date().allow(null).optional(),
|
||||
deleted_at: Validator.date().allow(null).optional(),
|
||||
metadata: Validator.object().allow(null).optional(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(discountRule)
|
||||
@@ -117,6 +105,7 @@ class DiscountService extends BaseService {
|
||||
|
||||
/**
|
||||
* @param {Object} selector - the query object for find
|
||||
* @param {Object} config - the config object containing query settings
|
||||
* @return {Promise} the result of the find operation
|
||||
*/
|
||||
async list(selector = {}, config = { relations: [], skip: 0, take: 10 }) {
|
||||
@@ -130,6 +119,7 @@ class DiscountService extends BaseService {
|
||||
|
||||
/**
|
||||
* @param {Object} selector - the query object for find
|
||||
* @param {Object} config - the config object containing query settings
|
||||
* @return {Promise} the result of the find operation
|
||||
*/
|
||||
async listAndCount(
|
||||
@@ -153,11 +143,11 @@ class DiscountService extends BaseService {
|
||||
|
||||
delete where.code
|
||||
|
||||
query.where = qb => {
|
||||
query.where = (qb) => {
|
||||
qb.where(where)
|
||||
|
||||
qb.andWhere(
|
||||
new Brackets(qb => {
|
||||
new Brackets((qb) => {
|
||||
qb.where({ code: ILike(`%${q}%`) })
|
||||
})
|
||||
)
|
||||
@@ -176,16 +166,20 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the result of the create operation
|
||||
*/
|
||||
async create(discount) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRepo = manager.getCustomRepository(this.discountRepository_)
|
||||
const ruleRepo = manager.getCustomRepository(this.discountRuleRepository_)
|
||||
|
||||
if (discount.rule?.valid_for) {
|
||||
discount.rule.valid_for = discount.rule.valid_for.map((id) => ({ id }))
|
||||
}
|
||||
|
||||
const validatedRule = this.validateDiscountRule_(discount.rule)
|
||||
|
||||
if (discount.regions) {
|
||||
discount.regions = await Promise.all(
|
||||
discount.regions.map(regionId =>
|
||||
this.regionService_.retrieve(regionId)
|
||||
discount.regions.map((regionId) =>
|
||||
this.regionService_.withTransaction(manager).retrieve(regionId)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -205,6 +199,7 @@ class DiscountService extends BaseService {
|
||||
/**
|
||||
* Gets a discount by id.
|
||||
* @param {string} discountId - id of discount to retrieve
|
||||
* @param {Object} config - the config object containing query settings
|
||||
* @return {Promise<Discount>} the discount
|
||||
*/
|
||||
async retrieve(discountId, config = {}) {
|
||||
@@ -229,6 +224,7 @@ class DiscountService extends BaseService {
|
||||
/**
|
||||
* Gets a discount by discount code.
|
||||
* @param {string} discountCode - discount code of discount to retrieve
|
||||
* @param {array} relations - list of relations
|
||||
* @return {Promise<Discount>} the discount document
|
||||
*/
|
||||
async retrieveByCode(discountCode, relations = []) {
|
||||
@@ -265,7 +261,7 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async update(discountId, update) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRepo = manager.getCustomRepository(this.discountRepository_)
|
||||
|
||||
const discount = await this.retrieve(discountId)
|
||||
@@ -283,7 +279,7 @@ class DiscountService extends BaseService {
|
||||
|
||||
if (regions) {
|
||||
discount.regions = await Promise.all(
|
||||
regions.map(regionId => this.regionService_.retrieve(regionId))
|
||||
regions.map((regionId) => this.regionService_.retrieve(regionId))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -293,6 +289,11 @@ class DiscountService extends BaseService {
|
||||
|
||||
if (rule) {
|
||||
discount.rule = this.validateDiscountRule_(rule)
|
||||
if (rule.valid_for) {
|
||||
discount.rule.valid_for = discount.rule.valid_for.map((id) => ({
|
||||
id,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(rest)) {
|
||||
@@ -307,11 +308,11 @@ class DiscountService extends BaseService {
|
||||
/**
|
||||
* Creates a dynamic code for a discount id.
|
||||
* @param {string} discountId - the id of the discount to create a code for
|
||||
* @param {string} code - the code to identify the discount by
|
||||
* @param {Object} data - the object containing a code to identify the discount by
|
||||
* @return {Promise} the newly created dynamic code
|
||||
*/
|
||||
async createDynamicCode(discountId, data) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRepo = manager.getCustomRepository(this.discountRepository_)
|
||||
|
||||
const discount = await this.retrieve(discountId)
|
||||
@@ -360,13 +361,15 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the newly created dynamic code
|
||||
*/
|
||||
async deleteDynamicCode(discountId, code) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRepo = manager.getCustomRepository(this.discountRepository_)
|
||||
const discount = await discountRepo.findOne({
|
||||
where: { parent_discount_id: discountId, code },
|
||||
})
|
||||
|
||||
if (!discount) return Promise.resolve()
|
||||
if (!discount) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
await discountRepo.softRemove(discount)
|
||||
|
||||
@@ -381,7 +384,7 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async addValidProduct(discountId, productId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRuleRepo = manager.getCustomRepository(
|
||||
this.discountRuleRepository_
|
||||
)
|
||||
@@ -392,7 +395,7 @@ class DiscountService extends BaseService {
|
||||
|
||||
const { rule } = discount
|
||||
|
||||
const exists = rule.valid_for.find(p => p.id === productId)
|
||||
const exists = rule.valid_for.find((p) => p.id === productId)
|
||||
// If product is already present, we return early
|
||||
if (exists) {
|
||||
return rule
|
||||
@@ -414,7 +417,7 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async removeValidProduct(discountId, productId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRuleRepo = manager.getCustomRepository(
|
||||
this.discountRuleRepository_
|
||||
)
|
||||
@@ -425,13 +428,13 @@ class DiscountService extends BaseService {
|
||||
|
||||
const { rule } = discount
|
||||
|
||||
const exists = rule.valid_for.find(p => p.id === productId)
|
||||
const exists = rule.valid_for.find((p) => p.id === productId)
|
||||
// If product is not present, we return early
|
||||
if (!exists) {
|
||||
return rule
|
||||
}
|
||||
|
||||
rule.valid_for = rule.valid_for.filter(p => p.id !== productId)
|
||||
rule.valid_for = rule.valid_for.filter((p) => p.id !== productId)
|
||||
|
||||
const updated = await discountRuleRepo.save(rule)
|
||||
return updated
|
||||
@@ -445,14 +448,14 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async addRegion(discountId, regionId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRepo = manager.getCustomRepository(this.discountRepository_)
|
||||
|
||||
const discount = await this.retrieve(discountId, {
|
||||
relations: ["regions"],
|
||||
})
|
||||
|
||||
const exists = discount.regions.find(r => r.id === regionId)
|
||||
const exists = discount.regions.find((r) => r.id === regionId)
|
||||
// If region is already present, we return early
|
||||
if (exists) {
|
||||
return discount
|
||||
@@ -474,20 +477,20 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async removeRegion(discountId, regionId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRepo = manager.getCustomRepository(this.discountRepository_)
|
||||
|
||||
const discount = await this.retrieve(discountId, {
|
||||
relations: ["regions"],
|
||||
})
|
||||
|
||||
const exists = discount.regions.find(r => r.id === regionId)
|
||||
const exists = discount.regions.find((r) => r.id === regionId)
|
||||
// If region is not present, we return early
|
||||
if (!exists) {
|
||||
return discount
|
||||
}
|
||||
|
||||
discount.regions = discount.regions.filter(r => r.id !== regionId)
|
||||
discount.regions = discount.regions.filter((r) => r.id !== regionId)
|
||||
|
||||
const updated = await discountRepo.save(discount)
|
||||
return updated
|
||||
@@ -500,12 +503,14 @@ class DiscountService extends BaseService {
|
||||
* @return {Promise} the result of the delete operation
|
||||
*/
|
||||
async delete(discountId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const discountRepo = manager.getCustomRepository(this.discountRepository_)
|
||||
|
||||
const discount = await discountRepo.findOne({ where: { id: discountId } })
|
||||
|
||||
if (!discount) return Promise.resolve()
|
||||
if (!discount) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
await discountRepo.softRemove(discount)
|
||||
|
||||
@@ -515,7 +520,7 @@ class DiscountService extends BaseService {
|
||||
|
||||
/**
|
||||
* Decorates a discount.
|
||||
* @param {Discount} discount - the discount to decorate.
|
||||
* @param {string} discountId - id of discount to decorate
|
||||
* @param {string[]} fields - the fields to include.
|
||||
* @param {string[]} expandFields - fields to expand.
|
||||
* @return {Discount} return the decorated discount.
|
||||
|
||||
@@ -250,10 +250,10 @@ class DraftOrderService extends BaseService {
|
||||
}
|
||||
|
||||
const {
|
||||
items,
|
||||
shipping_methods,
|
||||
discounts,
|
||||
no_notification_order,
|
||||
items,
|
||||
...rest
|
||||
} = data
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import _ from "lodash"
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
|
||||
/**
|
||||
* Handles Fulfillments
|
||||
* @implements BaseService
|
||||
* @extends BaseService
|
||||
*/
|
||||
class FulfillmentService extends BaseService {
|
||||
constructor({
|
||||
@@ -61,7 +60,7 @@ class FulfillmentService extends BaseService {
|
||||
}
|
||||
|
||||
partitionItems_(shippingMethods, items) {
|
||||
let partitioned = []
|
||||
const partitioned = []
|
||||
// partition order items to their dedicated shipping method
|
||||
for (const method of shippingMethods) {
|
||||
const temp = { shipping_method: method }
|
||||
@@ -95,12 +94,12 @@ class FulfillmentService extends BaseService {
|
||||
async getFulfillmentItems_(order, items, transformer) {
|
||||
const toReturn = await Promise.all(
|
||||
items.map(async ({ item_id, quantity }) => {
|
||||
const item = order.items.find(i => i.id === item_id)
|
||||
const item = order.items.find((i) => i.id === item_id)
|
||||
return transformer(item, quantity)
|
||||
})
|
||||
)
|
||||
|
||||
return toReturn.filter(i => !!i)
|
||||
return toReturn.filter((i) => !!i)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,6 +136,7 @@ class FulfillmentService extends BaseService {
|
||||
/**
|
||||
* Retrieves a fulfillment by its id.
|
||||
* @param {string} id - the id of the fulfillment to retrieve
|
||||
* @param {object} config - optional values to include with fulfillmentRepository query
|
||||
* @return {Fulfillment} the fulfillment
|
||||
*/
|
||||
async retrieve(id, config = {}) {
|
||||
@@ -165,11 +165,11 @@ class FulfillmentService extends BaseService {
|
||||
* those partitions.
|
||||
* @param {Order} order - order to create fulfillment for
|
||||
* @param {{ item_id: string, quantity: number}[]} itemsToFulfill - the items in the order to fulfill
|
||||
* @param {object} metadata - potential metadata to add
|
||||
* @param {object} custom - potential custom values to add
|
||||
* @return {Fulfillment[]} the created fulfillments
|
||||
*/
|
||||
async createFulfillment(order, itemsToFulfill, custom = {}) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const fulfillmentRepository = manager.getCustomRepository(
|
||||
this.fulfillmentRepository_
|
||||
)
|
||||
@@ -190,18 +190,19 @@ class FulfillmentService extends BaseService {
|
||||
const ful = fulfillmentRepository.create({
|
||||
...custom,
|
||||
provider_id: shipping_method.shipping_option.provider_id,
|
||||
items: items.map(i => ({ item_id: i.id, quantity: i.quantity })),
|
||||
items: items.map((i) => ({ item_id: i.id, quantity: i.quantity })),
|
||||
data: {},
|
||||
})
|
||||
|
||||
let result = await fulfillmentRepository.save(ful)
|
||||
const result = await fulfillmentRepository.save(ful)
|
||||
|
||||
result.data = await this.fulfillmentProviderService_.createFulfillment(
|
||||
shipping_method,
|
||||
items,
|
||||
{ ...order },
|
||||
{ ...result }
|
||||
)
|
||||
result.data =
|
||||
await this.fulfillmentProviderService_.createFulfillment(
|
||||
shipping_method,
|
||||
items,
|
||||
{ ...order },
|
||||
{ ...result }
|
||||
)
|
||||
|
||||
return fulfillmentRepository.save(result)
|
||||
})
|
||||
@@ -220,7 +221,7 @@ class FulfillmentService extends BaseService {
|
||||
*
|
||||
*/
|
||||
cancelFulfillment(fulfillmentOrId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
let id = fulfillmentOrId
|
||||
if (typeof fulfillmentOrId === "object") {
|
||||
id = fulfillmentOrId.id
|
||||
@@ -260,9 +261,9 @@ class FulfillmentService extends BaseService {
|
||||
|
||||
/**
|
||||
* Creates a shipment by marking a fulfillment as shipped. Adds
|
||||
* tracking numbers and potentially more metadata.
|
||||
* tracking links and potentially more metadata.
|
||||
* @param {Order} fulfillmentId - the fulfillment to ship
|
||||
* @param {TrackingLink[]} trackingNumbers - tracking numbers for the shipment
|
||||
* @param {TrackingLink[]} trackingLinks - tracking links for the shipment
|
||||
* @param {object} config - potential configuration settings, such as no_notification and metadata
|
||||
* @return {Fulfillment} the shipped fulfillment
|
||||
*/
|
||||
@@ -276,7 +277,7 @@ class FulfillmentService extends BaseService {
|
||||
) {
|
||||
const { metadata, no_notification } = config
|
||||
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const fulfillmentRepository = manager.getCustomRepository(
|
||||
this.fulfillmentRepository_
|
||||
)
|
||||
@@ -298,7 +299,7 @@ class FulfillmentService extends BaseService {
|
||||
const now = new Date()
|
||||
fulfillment.shipped_at = now
|
||||
|
||||
fulfillment.tracking_links = trackingLinks.map(tl =>
|
||||
fulfillment.tracking_links = trackingLinks.map((tl) =>
|
||||
trackingLinkRepo.create(tl)
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Brackets } from "typeorm"
|
||||
|
||||
/**
|
||||
* Provides layer to manipulate gift cards.
|
||||
* @implements BaseService
|
||||
* @extends BaseService
|
||||
*/
|
||||
class GiftCardService extends BaseService {
|
||||
static Events = {
|
||||
@@ -101,7 +101,7 @@ class GiftCardService extends BaseService {
|
||||
.select(["gift_card.id"])
|
||||
.where(where)
|
||||
.andWhere(
|
||||
new Brackets(qb => {
|
||||
new Brackets((qb) => {
|
||||
return qb
|
||||
.where(`gift_card.code ILIKE :q`, { q: `%${q}%` })
|
||||
.orWhere(`display_id::varchar(255) ILIKE :dId`, { dId: `${q}` })
|
||||
@@ -111,14 +111,14 @@ class GiftCardService extends BaseService {
|
||||
|
||||
return giftCardRepo.findWithRelations(
|
||||
rels,
|
||||
raw.map(i => i.id)
|
||||
raw.map((i) => i.id)
|
||||
)
|
||||
}
|
||||
return giftCardRepo.findWithRelations(rels, query)
|
||||
}
|
||||
|
||||
async createTransaction(data) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const gctRepo = manager.getCustomRepository(this.giftCardTransactionRepo_)
|
||||
const created = gctRepo.create(data)
|
||||
const saved = await gctRepo.save(created)
|
||||
@@ -132,7 +132,7 @@ class GiftCardService extends BaseService {
|
||||
* @return {Promise<GiftCard>} the result of the create operation
|
||||
*/
|
||||
async create(giftCard) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const giftCardRepo = manager.getCustomRepository(this.giftCardRepository_)
|
||||
|
||||
if (!giftCard.region_id) {
|
||||
@@ -169,6 +169,7 @@ class GiftCardService extends BaseService {
|
||||
/**
|
||||
* Gets a gift card by id.
|
||||
* @param {string} giftCardId - id of gift card to retrieve
|
||||
* @param {object} config - optional values to include with gift card query
|
||||
* @return {Promise<GiftCard>} the gift card
|
||||
*/
|
||||
async retrieve(giftCardId, config = {}) {
|
||||
@@ -244,7 +245,7 @@ class GiftCardService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async update(giftCardId, update) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const giftCardRepo = manager.getCustomRepository(this.giftCardRepository_)
|
||||
|
||||
const giftCard = await this.retrieve(giftCardId)
|
||||
@@ -285,12 +286,14 @@ class GiftCardService extends BaseService {
|
||||
* @return {Promise} the result of the delete operation
|
||||
*/
|
||||
async delete(giftCardId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const giftCardRepo = manager.getCustomRepository(this.giftCardRepository_)
|
||||
|
||||
const giftCard = await giftCardRepo.findOne({ where: { id: giftCardId } })
|
||||
|
||||
if (!giftCard) return Promise.resolve()
|
||||
if (!giftCard) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
await giftCardRepo.softRemove(giftCard)
|
||||
|
||||
|
||||
@@ -178,6 +178,7 @@ class OrderService extends BaseService {
|
||||
|
||||
/**
|
||||
* @param {Object} selector - the query object for find
|
||||
* @param {Object} config - the config to be used for find
|
||||
* @return {Promise} the result of the find operation
|
||||
*/
|
||||
async list(
|
||||
@@ -187,9 +188,8 @@ class OrderService extends BaseService {
|
||||
const orderRepo = this.manager_.getCustomRepository(this.orderRepository_)
|
||||
const query = this.buildQuery_(selector, config)
|
||||
|
||||
const { select, relations, totalsToSelect } = this.transformQueryForTotals_(
|
||||
config
|
||||
)
|
||||
const { select, relations, totalsToSelect } =
|
||||
this.transformQueryForTotals_(config)
|
||||
|
||||
if (select && select.length) {
|
||||
query.select = select
|
||||
@@ -201,7 +201,7 @@ class OrderService extends BaseService {
|
||||
|
||||
const raw = await orderRepo.find(query)
|
||||
|
||||
return raw.map(r => this.decorateTotals_(r, totalsToSelect))
|
||||
return raw.map((r) => this.decorateTotals_(r, totalsToSelect))
|
||||
}
|
||||
|
||||
async listAndCount(
|
||||
@@ -231,11 +231,11 @@ class OrderService extends BaseService {
|
||||
},
|
||||
}
|
||||
|
||||
query.where = qb => {
|
||||
query.where = (qb) => {
|
||||
qb.where(where)
|
||||
|
||||
qb.andWhere(
|
||||
new Brackets(qb => {
|
||||
new Brackets((qb) => {
|
||||
qb.where(`shipping_address.first_name ILIKE :qfn`, {
|
||||
qfn: `%${q}%`,
|
||||
})
|
||||
@@ -246,20 +246,19 @@ class OrderService extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
const { select, relations, totalsToSelect } = this.transformQueryForTotals_(
|
||||
config
|
||||
)
|
||||
const { select, relations, totalsToSelect } =
|
||||
this.transformQueryForTotals_(config)
|
||||
|
||||
if (select && select.length) {
|
||||
query.select = select
|
||||
}
|
||||
|
||||
let rels = relations
|
||||
const rels = relations
|
||||
delete query.relations
|
||||
|
||||
const raw = await orderRepo.findWithRelations(rels, query)
|
||||
const count = await orderRepo.count(query)
|
||||
const orders = raw.map(r => this.decorateTotals_(r, totalsToSelect))
|
||||
const orders = raw.map((r) => this.decorateTotals_(r, totalsToSelect))
|
||||
|
||||
return [orders, count]
|
||||
}
|
||||
@@ -289,13 +288,15 @@ class OrderService extends BaseService {
|
||||
"swaps.additional_items.refundable",
|
||||
]
|
||||
|
||||
const totalsToSelect = select.filter(v => totalFields.includes(v))
|
||||
const totalsToSelect = select.filter((v) => totalFields.includes(v))
|
||||
if (totalsToSelect.length > 0) {
|
||||
const relationSet = new Set(relations)
|
||||
relationSet.add("items")
|
||||
relationSet.add("swaps")
|
||||
relationSet.add("swaps.additional_items")
|
||||
relationSet.add("discounts")
|
||||
relationSet.add("discounts.rule")
|
||||
relationSet.add("discounts.rule.valid_for")
|
||||
relationSet.add("gift_cards")
|
||||
relationSet.add("gift_card_transactions")
|
||||
relationSet.add("refunds")
|
||||
@@ -303,7 +304,7 @@ class OrderService extends BaseService {
|
||||
relationSet.add("region")
|
||||
relations = [...relationSet]
|
||||
|
||||
select = select.filter(v => !totalFields.includes(v))
|
||||
select = select.filter((v) => !totalFields.includes(v))
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -316,15 +317,15 @@ class OrderService extends BaseService {
|
||||
/**
|
||||
* Gets an order by id.
|
||||
* @param {string} orderId - id of order to retrieve
|
||||
* @param {Object} config - config of order to retrieve
|
||||
* @return {Promise<Order>} the order document
|
||||
*/
|
||||
async retrieve(orderId, config = {}) {
|
||||
const orderRepo = this.manager_.getCustomRepository(this.orderRepository_)
|
||||
const validatedId = this.validateId_(orderId)
|
||||
|
||||
const { select, relations, totalsToSelect } = this.transformQueryForTotals_(
|
||||
config
|
||||
)
|
||||
const { select, relations, totalsToSelect } =
|
||||
this.transformQueryForTotals_(config)
|
||||
|
||||
const query = {
|
||||
where: { id: validatedId },
|
||||
@@ -355,14 +356,14 @@ class OrderService extends BaseService {
|
||||
/**
|
||||
* Gets an order by cart id.
|
||||
* @param {string} cartId - cart id to find order
|
||||
* @param {Object} config - the config to be used to find order
|
||||
* @return {Promise<Order>} the order document
|
||||
*/
|
||||
async retrieveByCartId(cartId, config = {}) {
|
||||
const orderRepo = this.manager_.getCustomRepository(this.orderRepository_)
|
||||
|
||||
const { select, relations, totalsToSelect } = this.transformQueryForTotals_(
|
||||
config
|
||||
)
|
||||
const { select, relations, totalsToSelect } =
|
||||
this.transformQueryForTotals_(config)
|
||||
|
||||
const query = {
|
||||
where: { cart_id: cartId },
|
||||
@@ -395,7 +396,7 @@ class OrderService extends BaseService {
|
||||
* @return {Promise<Order>} the order document
|
||||
*/
|
||||
async existsByCartId(cartId) {
|
||||
const order = await this.retrieveByCartId(cartId).catch(_ => undefined)
|
||||
const order = await this.retrieveByCartId(cartId).catch((_) => undefined)
|
||||
if (!order) {
|
||||
return false
|
||||
}
|
||||
@@ -407,7 +408,7 @@ class OrderService extends BaseService {
|
||||
* @return {Promise} the result of the find operation
|
||||
*/
|
||||
async completeOrder(orderId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId)
|
||||
|
||||
if (order.status === "canceled") {
|
||||
@@ -426,7 +427,7 @@ class OrderService extends BaseService {
|
||||
}
|
||||
)
|
||||
|
||||
await completeOrderJob.finished().catch(error => {
|
||||
await completeOrderJob.finished().catch((error) => {
|
||||
throw error
|
||||
})
|
||||
|
||||
@@ -443,7 +444,7 @@ class OrderService extends BaseService {
|
||||
* @return {Promise} resolves to the creation result.
|
||||
*/
|
||||
async createFromCart(cartId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const cart = await this.cartService_
|
||||
.withTransaction(manager)
|
||||
.retrieve(cartId, {
|
||||
@@ -453,6 +454,8 @@ class OrderService extends BaseService {
|
||||
"payment",
|
||||
"items",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"gift_cards",
|
||||
"shipping_methods",
|
||||
],
|
||||
@@ -615,6 +618,7 @@ class OrderService extends BaseService {
|
||||
* @param {string} fulfillmentId - the fulfillment that has now been shipped
|
||||
* @param {TrackingLink[]} trackingLinks - array of tracking numebers
|
||||
* associated with the shipment
|
||||
* @param {Object} config - the config of the order that has been shipped
|
||||
* @param {Dictionary<String, String>} metadata - optional metadata to add to
|
||||
* the fulfillment
|
||||
* @return {order} the resulting order following the update.
|
||||
@@ -630,7 +634,7 @@ class OrderService extends BaseService {
|
||||
) {
|
||||
const { metadata, no_notification } = config
|
||||
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId, { relations: ["items"] })
|
||||
const shipment = await this.fulfillmentService_.retrieve(fulfillmentId)
|
||||
|
||||
@@ -662,7 +666,7 @@ class OrderService extends BaseService {
|
||||
|
||||
order.fulfillment_status = "shipped"
|
||||
for (const item of order.items) {
|
||||
const shipped = shipmentRes.items.find(si => si.item_id === item.id)
|
||||
const shipped = shipmentRes.items.find((si) => si.item_id === item.id)
|
||||
if (shipped) {
|
||||
const shippedQty = (item.shipped_quantity || 0) + shipped.quantity
|
||||
if (shippedQty !== item.quantity) {
|
||||
@@ -696,11 +700,11 @@ class OrderService extends BaseService {
|
||||
|
||||
/**
|
||||
* Creates an order
|
||||
* @param {object} order - the order to create
|
||||
* @param {object} data - the data to create an order
|
||||
* @return {Promise} resolves to the creation result.
|
||||
*/
|
||||
async create(data) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const orderRepo = manager.getCustomRepository(this.orderRepository_)
|
||||
const order = orderRepo.create(data)
|
||||
const result = await orderRepo.save(order)
|
||||
@@ -716,7 +720,7 @@ class OrderService extends BaseService {
|
||||
|
||||
/**
|
||||
* Updates the order's billing address.
|
||||
* @param {string} orderId - the id of the order to update
|
||||
* @param {object} order - the order to update
|
||||
* @param {object} address - the value to set the billing address to
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
@@ -751,7 +755,7 @@ class OrderService extends BaseService {
|
||||
|
||||
/**
|
||||
* Updates the order's shipping address.
|
||||
* @param {string} orderId - the id of the order to update
|
||||
* @param {object} order - the order to update
|
||||
* @param {object} address - the value to set the shipping address to
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
@@ -783,7 +787,7 @@ class OrderService extends BaseService {
|
||||
}
|
||||
|
||||
async addShippingMethod(orderId, optionId, data, config = {}) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId, {
|
||||
select: ["subtotal"],
|
||||
relations: [
|
||||
@@ -841,7 +845,7 @@ class OrderService extends BaseService {
|
||||
* @return {Promise} resolves to the update result.
|
||||
*/
|
||||
async update(orderId, update) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId)
|
||||
|
||||
if (order.status === "canceled") {
|
||||
@@ -870,13 +874,7 @@ class OrderService extends BaseService {
|
||||
)
|
||||
}
|
||||
|
||||
const {
|
||||
metadata,
|
||||
items,
|
||||
billing_address,
|
||||
shipping_address,
|
||||
...rest
|
||||
} = update
|
||||
const { ...rest } = update
|
||||
|
||||
if ("metadata" in update) {
|
||||
order.metadata = this.setMetadata_(order, update.metadata)
|
||||
@@ -928,7 +926,7 @@ class OrderService extends BaseService {
|
||||
* @return {Promise} result of the update operation.
|
||||
*/
|
||||
async cancel(orderId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId, {
|
||||
relations: [
|
||||
"fulfillments",
|
||||
@@ -948,16 +946,16 @@ class OrderService extends BaseService {
|
||||
}
|
||||
|
||||
const throwErrorIf = (arr, pred, type) =>
|
||||
arr?.filter(pred).find(_ => {
|
||||
arr?.filter(pred).find((_) => {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_ALLOWED,
|
||||
`All ${type} must be canceled before canceling an order`
|
||||
)
|
||||
})
|
||||
const notCanceled = o => !o.canceled_at
|
||||
const notCanceled = (o) => !o.canceled_at
|
||||
|
||||
throwErrorIf(order.fulfillments, notCanceled, "fulfillments")
|
||||
throwErrorIf(order.returns, r => r.status !== "canceled", "returns")
|
||||
throwErrorIf(order.returns, (r) => r.status !== "canceled", "returns")
|
||||
throwErrorIf(order.swaps, notCanceled, "swaps")
|
||||
throwErrorIf(order.claims, notCanceled, "claims")
|
||||
|
||||
@@ -996,7 +994,7 @@ class OrderService extends BaseService {
|
||||
* @return {Promise} result of the update operation.
|
||||
*/
|
||||
async capturePayment(orderId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const orderRepo = manager.getCustomRepository(this.orderRepository_)
|
||||
const order = await this.retrieve(orderId, { relations: ["payments"] })
|
||||
|
||||
@@ -1013,7 +1011,7 @@ class OrderService extends BaseService {
|
||||
const result = await this.paymentProviderService_
|
||||
.withTransaction(manager)
|
||||
.capturePayment(p)
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
this.eventBus_
|
||||
.withTransaction(manager)
|
||||
.emit(OrderService.Events.PAYMENT_CAPTURE_FAILED, {
|
||||
@@ -1035,7 +1033,7 @@ class OrderService extends BaseService {
|
||||
}
|
||||
|
||||
order.payments = payments
|
||||
order.payment_status = payments.every(p => p.captured_at !== null)
|
||||
order.payment_status = payments.every((p) => p.captured_at !== null)
|
||||
? "captured"
|
||||
: "requires_action"
|
||||
|
||||
@@ -1091,6 +1089,8 @@ class OrderService extends BaseService {
|
||||
* we need to partition the order items, such that they can be sent
|
||||
* to their respective fulfillment provider.
|
||||
* @param {string} orderId - id of order to cancel.
|
||||
* @param {Object} itemsToFulfill - items to fulfil.
|
||||
* @param {Object} config - the config to cancel.
|
||||
* @return {Promise} result of the update operation.
|
||||
*/
|
||||
async createFulfillment(
|
||||
@@ -1103,7 +1103,7 @@ class OrderService extends BaseService {
|
||||
) {
|
||||
const { metadata, no_notification } = config
|
||||
|
||||
return this.atomicPhase_(async manager => {
|
||||
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
|
||||
@@ -1119,6 +1119,8 @@ class OrderService extends BaseService {
|
||||
],
|
||||
relations: [
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"region",
|
||||
"fulfillments",
|
||||
"shipping_address",
|
||||
@@ -1163,7 +1165,7 @@ class OrderService extends BaseService {
|
||||
// Update all line items to reflect fulfillment
|
||||
for (const item of order.items) {
|
||||
const fulfillmentItem = successfullyFulfilled.find(
|
||||
f => item.id === f.item_id
|
||||
(f) => item.id === f.item_id
|
||||
)
|
||||
|
||||
if (fulfillmentItem) {
|
||||
@@ -1211,10 +1213,10 @@ class OrderService extends BaseService {
|
||||
/**
|
||||
* Cancels a fulfillment (if related to an order)
|
||||
* @param {string} fulfillmentId - the ID of the fulfillment to cancel
|
||||
* @returns updated order
|
||||
* @return {Promise} updated order
|
||||
*/
|
||||
async cancelFulfillment(fulfillmentId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const canceled = await this.fulfillmentService_
|
||||
.withTransaction(manager)
|
||||
.cancelFulfillment(fulfillmentId)
|
||||
@@ -1258,12 +1260,12 @@ class OrderService extends BaseService {
|
||||
async getFulfillmentItems_(order, items, transformer) {
|
||||
const toReturn = await Promise.all(
|
||||
items.map(async ({ item_id, quantity }) => {
|
||||
const item = order.items.find(i => i.id.equals(item_id))
|
||||
const item = order.items.find((i) => i.id.equals(item_id))
|
||||
return transformer(item, quantity)
|
||||
})
|
||||
)
|
||||
|
||||
return toReturn.filter(i => !!i)
|
||||
return toReturn.filter((i) => !!i)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1273,7 +1275,7 @@ class OrderService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async archive(orderId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId)
|
||||
|
||||
if (order.status !== ("completed" || "refunded")) {
|
||||
@@ -1292,6 +1294,12 @@ class OrderService extends BaseService {
|
||||
|
||||
/**
|
||||
* Refunds a given amount back to the customer.
|
||||
* @param {string} orderId - id of the order to refund.
|
||||
* @param {float} refundAmount - the amount to refund.
|
||||
* @param {string} reason - the reason to refund.
|
||||
* @param {string} note - note for refund.
|
||||
* @param {Object} config - the config for refund.
|
||||
* @return {Promise} the result of the refund operation.
|
||||
*/
|
||||
async createRefund(
|
||||
orderId,
|
||||
@@ -1304,7 +1312,7 @@ class OrderService extends BaseService {
|
||||
) {
|
||||
const { no_notification } = config
|
||||
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId, {
|
||||
select: ["refundable_amount", "total", "refunded_total"],
|
||||
relations: ["payments"],
|
||||
@@ -1374,7 +1382,7 @@ class OrderService extends BaseService {
|
||||
}
|
||||
|
||||
if (totalsFields.includes("items.refundable")) {
|
||||
order.items = order.items.map(i => ({
|
||||
order.items = order.items.map((i) => ({
|
||||
...i,
|
||||
refundable: this.totalsService_.getLineItemRefund(order, {
|
||||
...i,
|
||||
@@ -1389,7 +1397,7 @@ class OrderService extends BaseService {
|
||||
order.swaps.length
|
||||
) {
|
||||
for (const s of order.swaps) {
|
||||
s.additional_items = s.additional_items.map(i => ({
|
||||
s.additional_items = s.additional_items.map((i) => ({
|
||||
...i,
|
||||
refundable: this.totalsService_.getLineItemRefund(order, {
|
||||
...i,
|
||||
@@ -1412,10 +1420,11 @@ class OrderService extends BaseService {
|
||||
* mismatches.
|
||||
* @param {string} orderId - the order to return.
|
||||
* @param {object} receivedReturn - the received return
|
||||
* @param {float} customRefundAmount - the custom refund amount return
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async registerReturnReceived(orderId, receivedReturn, customRefundAmount) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const order = await this.retrieve(orderId, {
|
||||
select: ["total", "refunded_total", "refundable_amount"],
|
||||
relations: ["items", "returns", "payments"],
|
||||
@@ -1435,7 +1444,7 @@ class OrderService extends BaseService {
|
||||
)
|
||||
}
|
||||
|
||||
let refundAmount = customRefundAmount || receivedReturn.refund_amount
|
||||
const refundAmount = customRefundAmount || receivedReturn.refund_amount
|
||||
|
||||
const orderRepo = manager.getCustomRepository(this.orderRepository_)
|
||||
|
||||
@@ -1504,7 +1513,7 @@ class OrderService extends BaseService {
|
||||
const keyPath = `metadata.${key}`
|
||||
return this.orderModel_
|
||||
.updateOne({ _id: validatedId }, { $unset: { [keyPath]: "" } })
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ class ProductService extends BaseService {
|
||||
|
||||
let product = productRepo.create(rest)
|
||||
|
||||
if (images && images.length) {
|
||||
if (images) {
|
||||
product.images = await this.upsertImages_(images)
|
||||
}
|
||||
|
||||
@@ -380,11 +380,11 @@ class ProductService extends BaseService {
|
||||
...rest
|
||||
} = update
|
||||
|
||||
if (!product.thumbnail && !update.thumbnail && images && images.length) {
|
||||
if (!product.thumbnail && !update.thumbnail && images?.length) {
|
||||
product.thumbnail = images[0]
|
||||
}
|
||||
|
||||
if (images && images.length) {
|
||||
if (images) {
|
||||
product.images = await this.upsertImages_(images)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import _ from "lodash"
|
||||
import { Validator, MedusaError } from "medusa-core-utils"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { BaseService } from "medusa-interfaces"
|
||||
import { countries } from "../utils/countries"
|
||||
|
||||
/**
|
||||
* Provides layer to manipulate regions.
|
||||
* @implements BaseService
|
||||
* @extends BaseService
|
||||
*/
|
||||
class RegionService extends BaseService {
|
||||
static Events = {
|
||||
@@ -83,11 +82,11 @@ class RegionService extends BaseService {
|
||||
|
||||
/**
|
||||
* Creates a region.
|
||||
* @param {Region} rawRegion - the unvalidated region
|
||||
* @param {Region} regionObject - the unvalidated region
|
||||
* @return {Region} the newly created region
|
||||
*/
|
||||
async create(regionObject) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepository = manager.getCustomRepository(
|
||||
this.regionRepository_
|
||||
)
|
||||
@@ -118,7 +117,7 @@ class RegionService extends BaseService {
|
||||
}
|
||||
|
||||
if (metadata) {
|
||||
regionObject.metadata = this.setMetadata_(region, metadata)
|
||||
regionObject.metadata = this.setMetadata_(regionObject, metadata)
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(validated)) {
|
||||
@@ -145,7 +144,7 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async update(regionId, update) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepository = manager.getCustomRepository(
|
||||
this.regionRepository_
|
||||
)
|
||||
@@ -218,17 +217,17 @@ class RegionService extends BaseService {
|
||||
|
||||
if (region.countries) {
|
||||
region.countries = await Promise.all(
|
||||
region.countries.map(countryCode =>
|
||||
region.countries.map((countryCode) =>
|
||||
this.validateCountry_(countryCode, id)
|
||||
)
|
||||
).catch(err => {
|
||||
).catch((err) => {
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
if (region.payment_providers) {
|
||||
region.payment_providers = await Promise.all(
|
||||
region.payment_providers.map(async pId => {
|
||||
region.payment_providers.map(async (pId) => {
|
||||
const pp = await ppRepository.findOne({ where: { id: pId } })
|
||||
if (!pp) {
|
||||
throw new MedusaError(
|
||||
@@ -244,7 +243,7 @@ class RegionService extends BaseService {
|
||||
|
||||
if (region.fulfillment_providers) {
|
||||
region.fulfillment_providers = await Promise.all(
|
||||
region.fulfillment_providers.map(async fId => {
|
||||
region.fulfillment_providers.map(async (fId) => {
|
||||
const fp = await fpRepository.findOne({ where: { id: fId } })
|
||||
if (!fp) {
|
||||
throw new MedusaError(
|
||||
@@ -283,7 +282,7 @@ class RegionService extends BaseService {
|
||||
.withTransaction(this.transactionManager_)
|
||||
.retrieve(["currencies"])
|
||||
|
||||
const storeCurrencies = store.currencies.map(curr => curr.code)
|
||||
const storeCurrencies = store.currencies.map((curr) => curr.code)
|
||||
|
||||
if (!storeCurrencies.includes(currencyCode.toLowerCase())) {
|
||||
throw new MedusaError(
|
||||
@@ -305,7 +304,7 @@ class RegionService extends BaseService {
|
||||
)
|
||||
|
||||
const countryCode = code.toUpperCase()
|
||||
const validCountry = countries.find(c => c.alpha2 === countryCode)
|
||||
const validCountry = countries.find((c) => c.alpha2 === countryCode)
|
||||
if (!validCountry) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
@@ -339,6 +338,7 @@ class RegionService extends BaseService {
|
||||
/**
|
||||
* Retrieves a region by its id.
|
||||
* @param {string} regionId - the id of the region to retrieve
|
||||
* @param {object} config - configuration settings
|
||||
* @return {Region} the region
|
||||
*/
|
||||
async retrieve(regionId, config = {}) {
|
||||
@@ -361,7 +361,8 @@ class RegionService extends BaseService {
|
||||
|
||||
/**
|
||||
* Lists all regions based on a query
|
||||
* @param {object} listOptions - query object for find
|
||||
* @param {object} selector - query object for find
|
||||
* @param {object} config - configuration settings
|
||||
* @return {Promise} result of the find operation
|
||||
*/
|
||||
async list(selector = {}, config = { relations: [], skip: 0, take: 10 }) {
|
||||
@@ -377,12 +378,14 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the delete operation
|
||||
*/
|
||||
async delete(regionId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepo = manager.getCustomRepository(this.regionRepository_)
|
||||
|
||||
const region = await regionRepo.findOne({ where: { id: regionId } })
|
||||
|
||||
if (!region) return Promise.resolve()
|
||||
if (!region) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
await regionRepo.softRemove(region)
|
||||
|
||||
@@ -397,7 +400,7 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async addCountry(regionId, code) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepo = manager.getCustomRepository(this.regionRepository_)
|
||||
|
||||
const country = await this.validateCountry_(code, regionId)
|
||||
@@ -407,7 +410,7 @@ class RegionService extends BaseService {
|
||||
// Check if region already has country
|
||||
if (
|
||||
region.countries &&
|
||||
region.countries.map(c => c.iso_2).includes(country.iso_2)
|
||||
region.countries.map((c) => c.iso_2).includes(country.iso_2)
|
||||
) {
|
||||
return region
|
||||
}
|
||||
@@ -434,7 +437,7 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async removeCountry(regionId, code) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepo = manager.getCustomRepository(this.regionRepository_)
|
||||
|
||||
const region = await this.retrieve(regionId, { relations: ["countries"] })
|
||||
@@ -442,13 +445,13 @@ class RegionService extends BaseService {
|
||||
// Check if region contains country. If not, we simpy resolve
|
||||
if (
|
||||
region.countries &&
|
||||
!region.countries.map(c => c.iso_2).includes(code)
|
||||
!region.countries.map((c) => c.iso_2).includes(code)
|
||||
) {
|
||||
return region
|
||||
}
|
||||
|
||||
region.countries = region.countries.filter(
|
||||
country => country.iso_2 !== code
|
||||
(country) => country.iso_2 !== code
|
||||
)
|
||||
|
||||
const updated = await regionRepo.save(region)
|
||||
@@ -470,7 +473,7 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async addPaymentProvider(regionId, providerId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepo = manager.getCustomRepository(this.regionRepository_)
|
||||
const ppRepo = manager.getCustomRepository(
|
||||
this.paymentProviderRepository_
|
||||
@@ -517,7 +520,7 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async addFulfillmentProvider(regionId, providerId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepo = manager.getCustomRepository(this.regionRepository_)
|
||||
const fpRepo = manager.getCustomRepository(
|
||||
this.fulfillmentProviderRepository_
|
||||
@@ -561,7 +564,7 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async removePaymentProvider(regionId, providerId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepo = manager.getCustomRepository(this.regionRepository_)
|
||||
|
||||
const region = await this.retrieve(regionId, {
|
||||
@@ -595,7 +598,7 @@ class RegionService extends BaseService {
|
||||
* @return {Promise} the result of the update operation
|
||||
*/
|
||||
async removeFulfillmentProvider(regionId, providerId) {
|
||||
return this.atomicPhase_(async manager => {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const regionRepo = manager.getCustomRepository(this.regionRepository_)
|
||||
|
||||
const region = await this.retrieve(regionId, {
|
||||
|
||||
Loaded 100 of 151 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user