### What
Add workflow for refreshing a payment collection.
The idea is that on all cart updates, we want two things to happen (in the context of payments) 1. the currently active payment sessions should be destroyed, and 2. the payment collection should be updated with the new cart total.
We do this to ensure that we always collect the correct payment amount.
From a customer perspective, this would mean that every time something on the cart is updated, the customer would need to enter their payment details anew.
To me, this is a good tradeoff to avoid inconsistencies with payment collection.
Additionally, I updated the Payment Module interface with `upsert` and `updated` following our established convention.
### Note
This PR depends on a fix to the `remoteJoiner` that @carlos-r-l-rodrigues is working on.
Update: Fix merged in #6602
Co-authored-by: Adrien de Peretti <25098370+adrien2p@users.noreply.github.com>
what:
- add util to transform get response to an update request
RESOLVES CORE-1687
Given an update data object, we can infer the `fields` and `selects` of a data object using a util we already have - `getSelectsAndRelationsFromObjectArray`. Using the `fields` and `selects`, we can call either the module `retrieve` or `list` method to get a snapshot of the data down to its exact attributes. We can pass this data into the revert step.
In the revert step, we just need to convert the snapshot received from `retrieve` or `list` to a shape that the `update` methods will accept. The util that is introduced in this PR aims to do exactly that, so that the revert step looks as simple as:
```
const { snapshotData, selects, relations } = revertInput
await promotionModule.updateCampaigns(
convertItemResponseToUpdateRequest(snapshotData, selects, relations)
)
```
entity before update:
```
Campaign: {
id: "campaign-test-1",
name: "test campaign",
budget: {
total: 2000
},
promotions: [{ id: "promotion-1" }],
rules: [
{ id: "rule-1", operator: "gt", value: "10" }
]
}
```
This is how the util will transform the data for different types of attributes in the object:
simple attributes:
```
invoke:
{
id: "campaign-test-1",
name: "change name",
}
compensate:
{
id: "test-1",
name: "test campaign"
}
```
one to one relationship:
```
invoke:
{
id: "campaign-test-1",
budget: { total: 4000 }
}
compensate:
{
id: "campaign-test-1",
budget: { total: 2000 }
}
```
one to many / many to many relationship:
```
invoke:
{
id: "campaign-test-1",
promotions: [{ id: "promotion-2" }]
rules: [
{ id: "rule-1", operator: "gt", value: "20" },
{ operator: "gt", value: "20" }
]
}
compensate:
{
id: "campaign-test-1",
promotions: [{ id: "promotion-1" }]
rules: [{ id: "rule-1", operator: "gt", value: "20" }]
}
```
all together:
```
invoke:
{
id: "campaign-test-1",
name: "change name",
promotions: [{ id: "promotion-2" }],
budget: { total: 4000 },
rules: [
{ id: "rule-1", operator: "gt", value: "20" },
{ operator: "gt", value: "20" }
]
}
compensate:
{
id: "test-1",
name: "test campaign",
promotions: [{ id: "promotion-1" }],
budget: { total: 2000 },
rules: [{ id: "rule-1", operator: "gt", value: "20" }],
}
```
**What**
> [!NOTE]
> I can see this pr becoming huge, so I d like to get this partial one merged 👍
- Fixes shared connection usage (mikro orm compare the instance to its own package and therefore was resulting in not trully reusing the provided connection leading to exhausting the connection pool as multiple connections was created and end up not being all destroyed properly under the hood, discovered in my integration tests)
- Create shipping options method implementation
- DTO's definition and service interface update
- integration tests
- Re work of the indexes with new util update
- Test runner utils to remove a big chunk of the boilerplate of the packages integrations
FIXES CORE-1742
**What**
- always return an index expression, also for unique constraints
**why**
- constraints can't be partial, meaning `UNIQUE ... WHERE` is not possible with constraints
- constraints are indicies under the hood so it doesn't change the behavior of the system when we're not using constraint specific features but just using them for `UNIQUE`
**What**
Fix the test utils database to trully run the migrations, the migration path is deprecated and not used anymore as umzung infer the path under the hood. It also fix the schema so that it is possible to specify different schema if needed.
The index helper can now create named constraints for uniqueness.
extracted [from](https://github.com/medusajs/medusa/pull/6381)
**What**
Initialize work on the fulfillment module entities.
This pr finally also include the indexes as i was working on some utilities i though it would make sense to test them directly.
Also this pr add a new utility to generate proper index for our entity properties. It also include a new monkey patch for the migration generator to handle most of if exists/not exists cases. The monkey patch is a workaround the fact that the transpilation does work well with the ECMA used by mikro orm and therefore we end up with some constructor issue when mikro orm try to instanciate the custom generator class extension.
**Comment**
- The rule part will likely evolved when we reach the point of rule filtering based data, so no need for details review I believe
FIXES CORE-1714
FIXES CORE-1715
FIXES CORE-1718
FIXES CORE-1722
FIXES CORE-1723
Current schema diagram

**What**
- Remove services that do not have any custom business and replace them with a simple interfaces
- Abstract module service provide the following base implementation
- retrieve
- list
- listAndCount
- delete
- softDelete
- restore
The above methods are created for the main model and also for each other models for which a config is provided
all method such as list, listAndCount, delete, softDelete and restore are pluralized with the model it refers to
**Migration**
- [x] product
- [x] pricing
- [x] promotion
- [x] cart
- [x] auth
- [x] customer
- [x] payment
- [x] Sales channel
- [x] Workflow-*
**Usage**
**Module**
The module service can now extend the ` ModulesSdkUtils.abstractModuleServiceFactory` which returns a class with the default implementation for each method and each model following the standard naming convention mentioned above.
This factory have 3 template arguments being the container, the main model DTO and an object representing the other model with a config object that contains at list the DTO and optionally a singular and plural property in case it needs to be set manually. It looks like the following:
```ts
export default class PricingModuleService</* ... */>
extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies,
PricingTypes.PriceSetDTO,
{
Currency: { dto: PricingTypes.CurrencyDTO }
MoneyAmount: { dto: PricingTypes.MoneyAmountDTO }
PriceSetMoneyAmount: { dto: PricingTypes.PriceSetMoneyAmountDTO }
PriceSetMoneyAmountRules: {
dto: PricingTypes.PriceSetMoneyAmountRulesDTO
}
PriceRule: { dto: PricingTypes.PriceRuleDTO }
RuleType: { dto: PricingTypes.RuleTypeDTO }
PriceList: { dto: PricingTypes.PriceListDTO }
PriceListRule: { dto: PricingTypes.PriceListRuleDTO }
}
>(PriceSet, generateMethodForModels, entityNameToLinkableKeysMap)
implements PricingTypes.IPricingModuleService
{
// ...
}
```
In the above, the singular and plural can be inferred as there is no tricky naming. Also, the default implementation does not remove the fact that you need to provides all the overloads etc in your module service interface. The above will provide a default implementation following the interface `AbstractModuleService` which is also auto generated, hence you will have the following methods available:
**for the main model**
- list
- retrieve
- listAndCount
- delete
- softDelete
- restore
**for the other models**
- list**MyModels**
- retrieve**MyModel**
- listAndCount**MyModels**
- delete**MyModels**
- softDelete**MyModels**
- restore**MyModels**
**Internal module service**
The internal module service can now extend `ModulesSdkUtils.internalModuleServiceFactory` which takes only one template argument which is the container type.
All internal services provides a default implementation for all retrieve, list, listAndCount, create, update, delete, softDelete, restore methods which follow the following interface `ModulesSdkTypes.InternalModuleService`:
```ts
export interface InternalModuleService<
TEntity extends {},
TContainer extends object = object
> {
get __container__(): TContainer
retrieve(
idOrObject: string,
config?: FindConfig<any>,
sharedContext?: Context
): Promise<TEntity>
retrieve(
idOrObject: object,
config?: FindConfig<any>,
sharedContext?: Context
): Promise<TEntity>
list(
filters?: FilterQuery<any> | BaseFilterable<FilterQuery<any>>,
config?: FindConfig<any>,
sharedContext?: Context
): Promise<TEntity[]>
listAndCount(
filters?: FilterQuery<any> | BaseFilterable<FilterQuery<any>>,
config?: FindConfig<any>,
sharedContext?: Context
): Promise<[TEntity[], number]>
create(data: any[], sharedContext?: Context): Promise<TEntity[]>
create(data: any, sharedContext?: Context): Promise<TEntity>
update(data: any[], sharedContext?: Context): Promise<TEntity[]>
update(data: any, sharedContext?: Context): Promise<TEntity>
update(
selectorAndData: {
selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
data: any
},
sharedContext?: Context
): Promise<TEntity[]>
update(
selectorAndData: {
selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
data: any
}[],
sharedContext?: Context
): Promise<TEntity[]>
delete(idOrSelector: string, sharedContext?: Context): Promise<void>
delete(idOrSelector: string[], sharedContext?: Context): Promise<void>
delete(idOrSelector: object, sharedContext?: Context): Promise<void>
delete(idOrSelector: object[], sharedContext?: Context): Promise<void>
delete(
idOrSelector: {
selector: FilterQuery<any> | BaseFilterable<FilterQuery<any>>
},
sharedContext?: Context
): Promise<void>
softDelete(
idsOrFilter: string[] | InternalFilterQuery,
sharedContext?: Context
): Promise<[TEntity[], Record<string, unknown[]>]>
restore(
idsOrFilter: string[] | InternalFilterQuery,
sharedContext?: Context
): Promise<[TEntity[], Record<string, unknown[]>]>
upsert(data: any[], sharedContext?: Context): Promise<TEntity[]>
upsert(data: any, sharedContext?: Context): Promise<TEntity>
}
```
When a service is auto generated you can use that interface to type your class property representing the expected internal service.
**Repositories**
The repositories can now extend `DALUtils.mikroOrmBaseRepositoryFactory` which takes one template argument being the entity or the template entity and provides all the default implementation. If the repository is auto generated you can type it using the `RepositoryService` interface. Here is the new interface typings.
```ts
export interface RepositoryService<T = any> extends BaseRepositoryService<T> {
find(options?: FindOptions<T>, context?: Context): Promise<T[]>
findAndCount(
options?: FindOptions<T>,
context?: Context
): Promise<[T[], number]>
create(data: any[], context?: Context): Promise<T[]>
// Becareful here, if you have a custom internal service, the update data should never be the entity otherwise
// both entity and update will point to the same ref and create issues with mikro orm
update(data: { entity; update }[], context?: Context): Promise<T[]>
delete(
idsOrPKs: FilterQuery<T> & BaseFilterable<FilterQuery<T>>,
context?: Context
): Promise<void>
/**
* Soft delete entities and cascade to related entities if configured.
*
* @param idsOrFilter
* @param context
*
* @returns [T[], Record<string, string[]>] the second value being the map of the entity names and ids that were soft deleted
*/
softDelete(
idsOrFilter: string[] | InternalFilterQuery,
context?: Context
): Promise<[T[], Record<string, unknown[]>]>
restore(
idsOrFilter: string[] | InternalFilterQuery,
context?: Context
): Promise<[T[], Record<string, unknown[]>]>
upsert(data: any[], context?: Context): Promise<T[]>
}
```
what:
- adds create endpoint for promotions including workflows and endpoint (RESOLVES CORE-1678)
- adds update endpoint for promotions including workflows and endpoint (RESOLVES CORE-1679)
- adds create endpoint for campaigns including workflows and endpoint (RESOLVES CORE-1684)
- adds update endpoint for campaigns including workflows and endpoint (RESOLVES CORE-1685)
what:
- adds compute actions for the following cases:
- items => each & across
- shipping_method => each & across
- order
- adds a remove compute actions when code is no longer present in adjustments array
RESOLVES CORE-1625
RESOLVES CORE-1626
RESOLVES CORE-1627
RESOLVES CORE-1628
RESOLVES CORE-1585
* feat(types,utils): added promotion create with rules
* chore: add rules to promotion and application method
* chore: use common code for rule and values
* chore: address pr reviews
* chore: fix test
**What**
At the moment, when importing something from medusa entry point, if two medusa packages are installed because of a plugin, the evaluation of the import can end up throwing that a workflow is already defined. To prevent that from happening, we can just not throw if it is already defined and just return prematurely and make it idempotent.
**What**
- transform remote query object back to string array
- get all fields and fields from given relations from a GraphQL schema
Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
* initial
* initial service
* update pricing module service
* add integration test for rule-type
* update pricing-module integration tests
* update pricing service interface
* feat(pricing): PriceSets as entry point to pricing module
* chore: add price set money amount
* chore: add price set money amount
* chore: change name of test
* chore: added changeset
* chore: use filterable props from money amount in price sets
* chore: update migrations
* test update integration test
* fix weird behavior
* Update packages/pricing/integration-tests/__fixtures__/rule-type/index.ts
Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
* Apply suggestions from code review
Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
* move rule-type to common
* chore: reset migration
* chore: remove incorrect conflicts
* chore: address review
* chore: remove ghost price list
* Apply suggestions from code review
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
* update id prefix
* use persist not persistAndflush
* rename key_value to rule_attribute
* more renaming
* feat(types,pricing): add price set money amount rules to pricing module
* chore: cleanup + add test cases for relationship update
* chore: revert package json
* chore: cleanup
* initial
* update pricing module service
* update pricing-module integration tests
* update pricing service interface
* chore: update migrations
* fix weird behavior
* Apply suggestions from code review
Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
* move rule-type to common
* chore: delete duplicate migration files
* fix(link-modules): Fix link module initialization (#4990)
**What**
Add a new configuration on the relationship to specify if the relation is consumed from an internal service (from medusa core). In that case do not check if the service is part of the loaded modules
* initial price rule
* rebase develop
* save here
* final changes to create
* update price rule integration test
* add module integraiton tests for price rules
* fix merge
* redo wierd order change
* pr cleanup
* pr cleanup
* pr cleanup
* update pr
* sort out migrations
* [wip]
* wip
* chore: temporarily emulate mikroorm internals
* currency code hard filtering
* before creating subqueries
* chore: wip
* chore: wip
* chore: add exact match multiple contexts
* chore: add one more test
* chore: add query that works with exact match
* chore: qb the thingy
* chore: add some comments
* chore: removed extra filter
* chore: added some more comments + prettify
* chore: test with carlos
* chore: add fallbacks and exact match tests
* chore: cleanup
* feat(types,pricing): add price set money amount rules to pricing module (#5065)
* initial
* initial service
* update pricing module service
* add integration test for rule-type
* update pricing-module integration tests
* update pricing service interface
* feat(pricing): PriceSets as entry point to pricing module
* chore: add price set money amount
* chore: add price set money amount
* chore: change name of test
* chore: added changeset
* chore: use filterable props from money amount in price sets
* chore: update migrations
* test update integration test
* fix weird behavior
* Update packages/pricing/integration-tests/__fixtures__/rule-type/index.ts
Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
* Apply suggestions from code review
Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
* move rule-type to common
* chore: reset migration
* chore: remove incorrect conflicts
* chore: address review
* chore: remove ghost price list
* Apply suggestions from code review
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
* update id prefix
* use persist not persistAndflush
* rename key_value to rule_attribute
* more renaming
* feat(types,pricing): add price set money amount rules to pricing module
* chore: cleanup + add test cases for relationship update
* chore: revert package json
* chore: cleanup
---------
Co-authored-by: Philip Korsholm <philip.korsholm@hotmail.com>
Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
* chore: minor cleanup
* chore: added money amount scoping
* chore: added review comments
* chore: update changset and undo test scoping
* chore: introduce group by util + no queries on empty context
* Feat/pricing module methods (#5218)
chore: add removePrices to pricing module
* Revert "Feat/pricing module methods (#5218)" (#5236)
This reverts commit 95c8aaa66423d290a35b6e736e5b187e12d44a36.
* chore: review changes
* chore: update schema
* chore: reset migration
---------
Co-authored-by: Philip Korsholm <philip.korsholm@hotmail.com>
Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
Co-authored-by: Adrien de Peretti <adrien.deperetti@gmail.com>
**What**
For simplicity and compatibility with the front, the fields are stored as an array of strings containing the list of fields that should be selected by a query. In order to reduce the delta between this object shape and what is expected by the remoteQuery when passing an object, we built util to make the translation from fields to config.
This will allow us to update the endpoint fields to specify what exactly needs to be selected and based on that we will be able to build the remote query object. Furthermore, it will allow us to drop back the functionality of custom fields and relations. we will still have to take into account the limit constraint of an url size including the parameters if a user want to select everything from a relation. In that case, we might maybe think about handling this case once the modules will export all available relations and fields so that the remote joiner would be able to pass them all automatically if the relation is present but a `*` is passed or no values in the fields during the translation with the util. But this is something we can come up in a separate iteration
**What**
There is actually an issue with using the `fields` query params with the way the repositories are using our custom query strategy. This pr aims to fix this issue by reworking the strategy.
What we had to do was to rework the way the selects are built for each subquery in order to follow the aliasing convention and to be taken into consideration. Alongside these changes, the join used to always select everything, this needed to be changed so that if there are any selects provided for a join, the join should not select everything and let the query select the fields that are requested.
Another notable change is that all the repositories are now using the repository util in order to centralize the customization and to have a single place to update when this kind of issue arises. This means that the eager relations when using the query builder are not necessarily taken into account. For that reason, I have removed the `shipping_option` eager option in favor of explicitly asking for the relations like we started to do it in some places.
FIXES CORE-1413