Chore/rm main entity concept (#7709)
**What** Update the `MedusaService` class, factory and types to remove the concept of main modules. The idea being that all method will be explicitly named and suffixes to represent the object you are trying to manipulate. This pr also includes various fixes in different modules Co-authored-by: Stevche Radevski <4820812+sradevski@users.noreply.github.com> Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
co-authored by
Stevche Radevski
Oli Juhl
parent
2895ccfba8
commit
48963f55ef
@@ -1,7 +1,15 @@
|
||||
import { moduleDefinition } from "./module-definition"
|
||||
import { ModuleExports } from "@medusajs/types"
|
||||
import { FulfillmentModuleService } from "@services"
|
||||
import loadProviders from "./loaders/providers"
|
||||
|
||||
export * from "./types"
|
||||
export * from "./models"
|
||||
export * from "./services"
|
||||
const service = FulfillmentModuleService
|
||||
const loaders = [loadProviders]
|
||||
|
||||
export const moduleDefinition: ModuleExports = {
|
||||
service,
|
||||
loaders,
|
||||
}
|
||||
export default moduleDefinition
|
||||
|
||||
// Module options types
|
||||
export { FulfillmentModuleOptions } from "./types"
|
||||
|
||||
@@ -1,94 +1,24 @@
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||
import { MapToConfig } from "@medusajs/utils"
|
||||
import {
|
||||
buildEntitiesNameToLinkableKeysMap,
|
||||
defineJoinerConfig,
|
||||
MapToConfig,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
FulfillmentSet,
|
||||
GeoZone,
|
||||
ServiceZone,
|
||||
ShippingOption,
|
||||
ShippingOptionRule,
|
||||
ShippingProfile,
|
||||
} from "@models"
|
||||
|
||||
export const LinkableKeys: Record<string, string> = {
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
}
|
||||
|
||||
const entityLinkableKeysMap: MapToConfig = {}
|
||||
Object.entries(LinkableKeys).forEach(([key, value]) => {
|
||||
entityLinkableKeysMap[value] ??= []
|
||||
entityLinkableKeysMap[value].push({
|
||||
mapTo: key,
|
||||
valueFrom: key.split("_").pop()!,
|
||||
})
|
||||
export const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
linkableKeys: {
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
},
|
||||
})
|
||||
|
||||
export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap
|
||||
|
||||
export const joinerConfig: ModuleJoinerConfig = {
|
||||
serviceName: Modules.FULFILLMENT,
|
||||
primaryKeys: ["id"],
|
||||
linkableKeys: LinkableKeys,
|
||||
alias: [
|
||||
{
|
||||
name: ["fulfillment_set", "fulfillment_sets"],
|
||||
args: {
|
||||
entity: FulfillmentSet.name,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option", "shipping_options"],
|
||||
args: {
|
||||
entity: ShippingOption.name,
|
||||
methodSuffix: "ShippingOptions",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_profile", "shipping_profiles"],
|
||||
args: {
|
||||
entity: ShippingProfile.name,
|
||||
methodSuffix: "ShippingProfiles",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment", "fulfillments"],
|
||||
args: {
|
||||
entity: Fulfillment.name,
|
||||
methodSuffix: "Fulfillments",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["fulfillment_provider", "fulfillment_providers"],
|
||||
args: {
|
||||
entity: FulfillmentProvider.name,
|
||||
methodSuffix: "FulfillmentProviders",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["service_zone", "service_zones"],
|
||||
args: {
|
||||
entity: ServiceZone.name,
|
||||
methodSuffix: "ServiceZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["geo_zone", "geo_zones"],
|
||||
args: {
|
||||
entity: GeoZone.name,
|
||||
methodSuffix: "GeoZones",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: ["shipping_option_rule", "shipping_option_rules"],
|
||||
args: {
|
||||
entity: ShippingOptionRule.name,
|
||||
methodSuffix: "ShippingOptionRules",
|
||||
},
|
||||
},
|
||||
],
|
||||
} as ModuleJoinerConfig
|
||||
export const entityNameToLinkableKeysMap: MapToConfig =
|
||||
buildEntitiesNameToLinkableKeysMap(joinerConfig.linkableKeys)
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { ModuleExports } from "@medusajs/types"
|
||||
import { FulfillmentModuleService } from "@services"
|
||||
import loadProviders from "./loaders/providers"
|
||||
|
||||
const service = FulfillmentModuleService
|
||||
const loaders = [loadProviders]
|
||||
|
||||
export const moduleDefinition: ModuleExports = {
|
||||
service,
|
||||
loaders,
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { Modules } from "@medusajs/modules-sdk"
|
||||
import * as Models from "@models"
|
||||
import { EOL } from "os"
|
||||
|
||||
const args = process.argv
|
||||
const path = args.pop() as string
|
||||
|
||||
export default (async () => {
|
||||
const { config } = await import("dotenv")
|
||||
config()
|
||||
if (!path) {
|
||||
throw new Error(
|
||||
`filePath is required.${EOL}Example: medusa-fulfillment-seed <filePath>`
|
||||
)
|
||||
}
|
||||
|
||||
const run = ModulesSdkUtils.buildSeedScript({
|
||||
moduleName: Modules.FULFILLMENT,
|
||||
models: Models,
|
||||
pathToMigrations: __dirname + "/../../migrations",
|
||||
seedHandler: async ({ manager, data }) => {
|
||||
// TODO: Add seed logic
|
||||
},
|
||||
})
|
||||
await run({ path })
|
||||
})()
|
||||
@@ -53,6 +53,7 @@ import { buildCreatedShippingOptionEvents } from "../utils/events"
|
||||
import FulfillmentProviderService from "./fulfillment-provider"
|
||||
|
||||
const generateMethodForModels = {
|
||||
FulfillmentSet,
|
||||
ServiceZone,
|
||||
ShippingOption,
|
||||
GeoZone,
|
||||
@@ -76,41 +77,29 @@ type InjectedDependencies = {
|
||||
fulfillmentService: ModulesSdkTypes.IMedusaInternalService<any>
|
||||
}
|
||||
|
||||
export default class FulfillmentModuleService<
|
||||
TEntity extends FulfillmentSet = FulfillmentSet,
|
||||
TServiceZoneEntity extends ServiceZone = ServiceZone,
|
||||
TGeoZoneEntity extends GeoZone = GeoZone,
|
||||
TShippingProfileEntity extends ShippingProfile = ShippingProfile,
|
||||
TShippingOptionEntity extends ShippingOption = ShippingOption,
|
||||
TShippingOptionRuleEntity extends ShippingOptionRule = ShippingOptionRule,
|
||||
TSippingOptionTypeEntity extends ShippingOptionType = ShippingOptionType,
|
||||
TFulfillmentEntity extends Fulfillment = Fulfillment
|
||||
>
|
||||
extends ModulesSdkUtils.MedusaService<
|
||||
FulfillmentTypes.FulfillmentSetDTO,
|
||||
{
|
||||
FulfillmentSet: { dto: FulfillmentTypes.FulfillmentSetDTO }
|
||||
ServiceZone: { dto: FulfillmentTypes.ServiceZoneDTO }
|
||||
ShippingOption: { dto: FulfillmentTypes.ShippingOptionDTO }
|
||||
GeoZone: { dto: FulfillmentTypes.GeoZoneDTO }
|
||||
ShippingProfile: { dto: FulfillmentTypes.ShippingProfileDTO }
|
||||
ShippingOptionRule: { dto: FulfillmentTypes.ShippingOptionRuleDTO }
|
||||
ShippingOptionType: { dto: FulfillmentTypes.ShippingOptionTypeDTO }
|
||||
FulfillmentProvider: { dto: FulfillmentTypes.FulfillmentProviderDTO }
|
||||
}
|
||||
>(FulfillmentSet, generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
export default class FulfillmentModuleService
|
||||
extends ModulesSdkUtils.MedusaService<{
|
||||
FulfillmentSet: { dto: FulfillmentTypes.FulfillmentSetDTO }
|
||||
ServiceZone: { dto: FulfillmentTypes.ServiceZoneDTO }
|
||||
ShippingOption: { dto: FulfillmentTypes.ShippingOptionDTO }
|
||||
GeoZone: { dto: FulfillmentTypes.GeoZoneDTO }
|
||||
ShippingProfile: { dto: FulfillmentTypes.ShippingProfileDTO }
|
||||
ShippingOptionRule: { dto: FulfillmentTypes.ShippingOptionRuleDTO }
|
||||
ShippingOptionType: { dto: FulfillmentTypes.ShippingOptionTypeDTO }
|
||||
FulfillmentProvider: { dto: FulfillmentTypes.FulfillmentProviderDTO }
|
||||
}>(generateMethodForModels, entityNameToLinkableKeysMap)
|
||||
implements IFulfillmentModuleService
|
||||
{
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
protected readonly fulfillmentSetService_: ModulesSdkTypes.IMedusaInternalService<TEntity>
|
||||
protected readonly serviceZoneService_: ModulesSdkTypes.IMedusaInternalService<TServiceZoneEntity>
|
||||
protected readonly geoZoneService_: ModulesSdkTypes.IMedusaInternalService<TGeoZoneEntity>
|
||||
protected readonly shippingProfileService_: ModulesSdkTypes.IMedusaInternalService<TShippingProfileEntity>
|
||||
protected readonly shippingOptionService_: ModulesSdkTypes.IMedusaInternalService<TShippingOptionEntity>
|
||||
protected readonly shippingOptionRuleService_: ModulesSdkTypes.IMedusaInternalService<TShippingOptionRuleEntity>
|
||||
protected readonly shippingOptionTypeService_: ModulesSdkTypes.IMedusaInternalService<TSippingOptionTypeEntity>
|
||||
protected readonly fulfillmentSetService_: ModulesSdkTypes.IMedusaInternalService<FulfillmentSet>
|
||||
protected readonly serviceZoneService_: ModulesSdkTypes.IMedusaInternalService<ServiceZone>
|
||||
protected readonly geoZoneService_: ModulesSdkTypes.IMedusaInternalService<GeoZone>
|
||||
protected readonly shippingProfileService_: ModulesSdkTypes.IMedusaInternalService<ShippingProfile>
|
||||
protected readonly shippingOptionService_: ModulesSdkTypes.IMedusaInternalService<ShippingOption>
|
||||
protected readonly shippingOptionRuleService_: ModulesSdkTypes.IMedusaInternalService<ShippingOptionRule>
|
||||
protected readonly shippingOptionTypeService_: ModulesSdkTypes.IMedusaInternalService<ShippingOptionType>
|
||||
protected readonly fulfillmentProviderService_: FulfillmentProviderService
|
||||
protected readonly fulfillmentService_: ModulesSdkTypes.IMedusaInternalService<TFulfillmentEntity>
|
||||
protected readonly fulfillmentService_: ModulesSdkTypes.IMedusaInternalService<Fulfillment>
|
||||
|
||||
constructor(
|
||||
{
|
||||
@@ -258,18 +247,19 @@ export default class FulfillmentModuleService<
|
||||
]
|
||||
}
|
||||
|
||||
create(
|
||||
// @ts-expect-error
|
||||
createFulfillmentSets(
|
||||
data: FulfillmentTypes.CreateFulfillmentSetDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.FulfillmentSetDTO[]>
|
||||
create(
|
||||
createFulfillmentSets(
|
||||
data: FulfillmentTypes.CreateFulfillmentSetDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.FulfillmentSetDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async create(
|
||||
async createFulfillmentSets(
|
||||
data:
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO[],
|
||||
@@ -277,7 +267,10 @@ export default class FulfillmentModuleService<
|
||||
): Promise<
|
||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||
> {
|
||||
const createdFulfillmentSets = await this.create_(data, sharedContext)
|
||||
const createdFulfillmentSets = await this.createFulfillmentSets_(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const returnedFulfillmentSets = Array.isArray(data)
|
||||
? createdFulfillmentSets
|
||||
@@ -289,12 +282,12 @@ export default class FulfillmentModuleService<
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
protected async create_(
|
||||
protected async createFulfillmentSets_(
|
||||
data:
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO
|
||||
| FulfillmentTypes.CreateFulfillmentSetDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[]> {
|
||||
): Promise<FulfillmentSet[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -360,7 +353,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateServiceZoneDTO[]
|
||||
| FulfillmentTypes.CreateServiceZoneDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TServiceZoneEntity[]> {
|
||||
): Promise<ServiceZone[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -424,7 +417,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateShippingOptionDTO[]
|
||||
| FulfillmentTypes.CreateShippingOptionDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingOptionEntity[]> {
|
||||
): Promise<ShippingOption[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -493,7 +486,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateShippingProfileDTO[]
|
||||
| FulfillmentTypes.CreateShippingProfileDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingProfileEntity[]> {
|
||||
): Promise<ShippingProfile[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -582,7 +575,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.CreateShippingOptionRuleDTO[]
|
||||
| FulfillmentTypes.CreateShippingOptionRuleDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingOptionRuleEntity[]> {
|
||||
): Promise<ShippingOptionRule[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -698,24 +691,28 @@ export default class FulfillmentModuleService<
|
||||
)
|
||||
}
|
||||
|
||||
update(
|
||||
// @ts-expect-error
|
||||
updateFulfillmentSets(
|
||||
data: FulfillmentTypes.UpdateFulfillmentSetDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.FulfillmentSetDTO[]>
|
||||
update(
|
||||
updateFulfillmentSets(
|
||||
data: FulfillmentTypes.UpdateFulfillmentSetDTO,
|
||||
sharedContext?: Context
|
||||
): Promise<FulfillmentTypes.FulfillmentSetDTO>
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
@EmitEvents()
|
||||
async update(
|
||||
async updateFulfillmentSets(
|
||||
data: UpdateFulfillmentSetDTO[] | UpdateFulfillmentSetDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
FulfillmentTypes.FulfillmentSetDTO[] | FulfillmentTypes.FulfillmentSetDTO
|
||||
> {
|
||||
const updatedFulfillmentSets = await this.update_(data, sharedContext)
|
||||
const updatedFulfillmentSets = await this.updateFulfillmentSets_(
|
||||
data,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
FulfillmentTypes.FulfillmentSetDTO | FulfillmentTypes.FulfillmentSetDTO[]
|
||||
@@ -723,10 +720,10 @@ export default class FulfillmentModuleService<
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
protected async update_(
|
||||
protected async updateFulfillmentSets_(
|
||||
data: UpdateFulfillmentSetDTO[] | UpdateFulfillmentSetDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity[] | TEntity> {
|
||||
): Promise<FulfillmentSet[] | FulfillmentSet> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -765,7 +762,7 @@ export default class FulfillmentModuleService<
|
||||
)
|
||||
}
|
||||
|
||||
const fulfillmentSetMap = new Map<string, TEntity>(
|
||||
const fulfillmentSetMap = new Map<string, FulfillmentSet>(
|
||||
fulfillmentSets.map((f) => [f.id, f])
|
||||
)
|
||||
|
||||
@@ -989,7 +986,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.UpdateServiceZoneDTO[]
|
||||
| FulfillmentTypes.UpdateServiceZoneDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TServiceZoneEntity | TServiceZoneEntity[]> {
|
||||
): Promise<ServiceZone | ServiceZone[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -1028,7 +1025,7 @@ export default class FulfillmentModuleService<
|
||||
)
|
||||
}
|
||||
|
||||
const serviceZoneMap = new Map<string, TServiceZoneEntity>(
|
||||
const serviceZoneMap = new Map<string, ServiceZone>(
|
||||
serviceZones.map((s) => [s.id, s])
|
||||
)
|
||||
|
||||
@@ -1185,7 +1182,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.UpsertServiceZoneDTO[]
|
||||
| FulfillmentTypes.UpsertServiceZoneDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TServiceZoneEntity[] | TServiceZoneEntity> {
|
||||
): Promise<ServiceZone[] | ServiceZone> {
|
||||
const input = Array.isArray(data) ? data : [data]
|
||||
const forUpdate = input.filter(
|
||||
(serviceZone): serviceZone is FulfillmentTypes.UpdateServiceZoneDTO =>
|
||||
@@ -1196,8 +1193,8 @@ export default class FulfillmentModuleService<
|
||||
!serviceZone.id
|
||||
)
|
||||
|
||||
const created: TServiceZoneEntity[] = []
|
||||
const updated: TServiceZoneEntity[] = []
|
||||
const created: ServiceZone[] = []
|
||||
const updated: ServiceZone[] = []
|
||||
|
||||
if (forCreate.length) {
|
||||
const createdServiceZones = await this.createServiceZones_(
|
||||
@@ -1280,7 +1277,7 @@ export default class FulfillmentModuleService<
|
||||
async updateShippingOptions_(
|
||||
data: UpdateShippingOptionsInput[] | UpdateShippingOptionsInput,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingOptionEntity | TShippingOptionEntity[]> {
|
||||
): Promise<ShippingOption | ShippingOption[]> {
|
||||
const dataArray = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!dataArray.length) {
|
||||
@@ -1506,7 +1503,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.UpsertShippingOptionDTO[]
|
||||
| FulfillmentTypes.UpsertShippingOptionDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingOptionEntity[] | TShippingOptionEntity> {
|
||||
): Promise<ShippingOption[] | ShippingOption> {
|
||||
const input = Array.isArray(data) ? data : [data]
|
||||
const forUpdate = input.filter(
|
||||
(shippingOption): shippingOption is UpdateShippingOptionsInput =>
|
||||
@@ -1519,8 +1516,8 @@ export default class FulfillmentModuleService<
|
||||
!shippingOption.id
|
||||
)
|
||||
|
||||
let created: TShippingOptionEntity[] = []
|
||||
let updated: TShippingOptionEntity[] = []
|
||||
let created: ShippingOption[] = []
|
||||
let updated: ShippingOption[] = []
|
||||
|
||||
if (forCreate.length) {
|
||||
const createdShippingOptions = await this.createShippingOptions_(
|
||||
@@ -1731,7 +1728,7 @@ export default class FulfillmentModuleService<
|
||||
| FulfillmentTypes.UpdateShippingOptionRuleDTO[]
|
||||
| FulfillmentTypes.UpdateShippingOptionRuleDTO,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TShippingOptionRuleEntity | TShippingOptionRuleEntity[]> {
|
||||
): Promise<ShippingOptionRule | ShippingOptionRule[]> {
|
||||
const data_ = Array.isArray(data) ? data : [data]
|
||||
|
||||
if (!data_.length) {
|
||||
@@ -1772,8 +1769,8 @@ export default class FulfillmentModuleService<
|
||||
id: string,
|
||||
data: FulfillmentTypes.UpdateFulfillmentDTO,
|
||||
@MedusaContext() sharedContext: Context
|
||||
): Promise<TFulfillmentEntity> {
|
||||
const existingFulfillment: TFulfillmentEntity =
|
||||
): Promise<Fulfillment> {
|
||||
const existingFulfillment: Fulfillment =
|
||||
await this.fulfillmentService_.retrieve(
|
||||
id,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user