Sales Order üzerinden Otomatik Tenant tanımlama

This commit is contained in:
Sedat Öztürk 2026-07-07 22:14:26 +03:00
parent 6dae9c4e94
commit c42a8d2bd1
11 changed files with 489 additions and 154 deletions

View file

@ -0,0 +1,10 @@
using System;
namespace Sozsoft.Platform.ListForms.DynamicApi;
public class CreateTenantFromOrderInput
{
public Guid OrderId { get; set; }
public string Name { get; set; }
public string MenuGroup { get; set; }
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
namespace Sozsoft.Platform.ListForms.DynamicApi;
@ -12,5 +12,5 @@ public interface IListFormDynamicApiAppService
Task PostTenantInsertAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input);
Task PostTenantUpdateAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input);
Task PostTenantDeleteAsync(DynamicApiBaseInput<string> input);
Task<Guid> PostCreateTenantFromOrderAsync(DynamicApiBaseInput<CreateTenantFromOrderInput> input);
}

View file

@ -16,6 +16,8 @@ using Sozsoft.Platform.BlobStoring;
using Sozsoft.Platform.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Sozsoft.Platform.Entities;
using Volo.Abp.Domain.Repositories;
namespace Sozsoft.Platform.ListForms.DynamicApi;
@ -35,6 +37,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
private readonly IConfiguration configuration;
private readonly IHostEnvironment hostEnvironment;
private readonly IOptions<IdentityOptions> identityOptions;
private readonly IRepository<Order, Guid> orderRepository;
public ListFormDynamicApiAppService(
ITenantRepository tenantRepository,
@ -45,7 +48,8 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
BlobManager blobCdnManager,
IConfiguration configuration,
IHostEnvironment hostEnvironment,
IOptions<IdentityOptions> identityOptions)
IOptions<IdentityOptions> identityOptions,
IRepository<Order, Guid> orderRepository)
{
this.tenantRepository = tenantRepository;
this.tenantManager = tenantManager;
@ -56,6 +60,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
this.configuration = configuration;
this.hostEnvironment = hostEnvironment;
this.identityOptions = identityOptions;
this.orderRepository = orderRepository;
}
private static Guid ParseGuid(string value)
@ -233,29 +238,89 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
[Authorize(TenantManagementPermissions.Tenants.Create)]
public async Task PostTenantInsertAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input)
{
var tenant = await tenantManager.CreateAsync(input.Data.Name);
await CreateTenantAsync(input.Data);
}
[Authorize(TenantManagementPermissions.Tenants.Create)]
public async Task<Guid> PostCreateTenantFromOrderAsync(DynamicApiBaseInput<CreateTenantFromOrderInput> input)
{
if (input.Data == null || input.Data.OrderId == Guid.Empty)
{
throw new UserFriendlyException(L["RecordNotFound"]);
}
if (input.Data.Name.IsNullOrWhiteSpace())
{
throw new UserFriendlyException("Tenant name is required.");
}
if (input.Data.MenuGroup.IsNullOrWhiteSpace())
{
throw new UserFriendlyException("Menu group is required.");
}
var order = await orderRepository.GetAsync(input.Data.OrderId)
?? throw new EntityNotFoundException(L["RecordNotFound"]);
if (order.TenantId.HasValue)
{
throw new UserFriendlyException("This order already has a tenant.");
}
var tenant = await CreateTenantAsync(new CreateUpdateTenantInput
{
Name = input.Data.Name,
IsActive = order.IsActive,
OrganizationName = order.OrganizationName,
Founder = order.Founder,
VknTckn = order.VknTckn ?? 0,
TaxOffice = order.TaxOffice,
Country = order.Country,
City = order.City,
District = order.District,
Address1 = order.Address1,
Address2 = order.Address2,
PostalCode = order.PostalCode,
PhoneNumber = order.PhoneNumber,
MobileNumber = order.MobileNumber,
FaxNumber = order.FaxNumber,
Email = order.Email,
Website = order.Website,
MenuGroup = input.Data.MenuGroup,
});
order.TenantId = tenant.Id;
order.MenuGroup = input.Data.MenuGroup;
await orderRepository.UpdateAsync(order, autoSave: true);
return tenant.Id;
}
private async Task<Tenant> CreateTenantAsync(CreateUpdateTenantInput input)
{
var tenant = await tenantManager.CreateAsync(input.Name);
var entity = await tenantRepository.InsertAsync(tenant, autoSave: true);
entity.SetIsActive(input.Data.IsActive);
entity.SetOrganizationName(input.Data.OrganizationName);
entity.SetFounder(input.Data.Founder);
entity.SetVknTckn(input.Data.VknTckn);
entity.SetTaxOffice(input.Data.TaxOffice);
entity.SetCountry(input.Data.Country);
entity.SetCity(input.Data.City);
entity.SetDistrict(input.Data.District);
entity.SetTownship(input.Data.Township);
entity.SetAddress1(input.Data.Address1);
entity.SetAddress2(input.Data.Address2);
entity.SetPostalCode(input.Data.PostalCode);
entity.SetPhoneNumber(input.Data.PhoneNumber);
entity.SetMobileNumber(input.Data.MobileNumber);
entity.SetFaxNumber(input.Data.FaxNumber);
entity.SetEmail(input.Data.Email);
entity.SetWebsite(input.Data.Website);
entity.SetMenuGroup(input.Data.MenuGroup);
entity.SetIsActive(input.IsActive);
entity.SetOrganizationName(input.OrganizationName);
entity.SetFounder(input.Founder);
entity.SetVknTckn(input.VknTckn);
entity.SetTaxOffice(input.TaxOffice);
entity.SetCountry(input.Country);
entity.SetCity(input.City);
entity.SetDistrict(input.District);
entity.SetTownship(input.Township);
entity.SetAddress1(input.Address1);
entity.SetAddress2(input.Address2);
entity.SetPostalCode(input.PostalCode);
entity.SetPhoneNumber(input.PhoneNumber);
entity.SetMobileNumber(input.MobileNumber);
entity.SetFaxNumber(input.FaxNumber);
entity.SetEmail(input.Email);
entity.SetWebsite(input.Website);
entity.SetMenuGroup(input.MenuGroup);
await tenantRepository.UpdateAsync(entity, autoSave: true);
return await tenantRepository.UpdateAsync(entity, autoSave: true);
}
[Authorize(TenantManagementPermissions.Tenants.Update)]

View file

@ -15,6 +15,7 @@ using Volo.Abp.PermissionManagement;
using Volo.Abp.TenantManagement;
using static Sozsoft.Platform.Data.Seeds.SeedConsts;
using Sozsoft.Languages;
using Sozsoft.Platform.ListForms;
namespace Sozsoft.Platform.Menus;
@ -31,6 +32,7 @@ public class MenuAppService : CrudAppService<
private readonly ITenantRepository _tenantRepository;
private readonly IPermissionDefinitionRecordRepository _permissionRepository;
private readonly LanguageTextAppService _languageTextAppService;
private readonly IRepository<MenuGroup, string> _menuGroupRepository;
public MenuAppService(
IRepository<Menu, Guid> menuRepository,
@ -38,7 +40,8 @@ public class MenuAppService : CrudAppService<
IRepository<LanguageText, Guid> languageTextRepository,
ITenantRepository tenantRepository,
IPermissionDefinitionRecordRepository permissionRepository,
LanguageTextAppService languageTextAppService
LanguageTextAppService languageTextAppService,
IRepository<MenuGroup, string> menuGroupRepository
) : base(menuRepository)
{
_menuRepository = menuRepository;
@ -47,6 +50,7 @@ public class MenuAppService : CrudAppService<
_tenantRepository = tenantRepository;
_permissionRepository = permissionRepository;
_languageTextAppService = languageTextAppService;
_menuGroupRepository = menuGroupRepository;
CreatePolicyName = $"{AppCodes.Menus.Menu}.Create";
UpdatePolicyName = $"{AppCodes.Menus.Menu}.Update";
@ -318,4 +322,18 @@ public class MenuAppService : CrudAppService<
return await base.CreateAsync(input);
}
public async Task<List<LookupDataDto>> GetMenuGroupsAsync()
{
var menuGroups = await _menuGroupRepository.GetListAsync();
return menuGroups
.OrderBy(menuGroup => menuGroup.Name)
.Select(menuGroup => new LookupDataDto
{
Key = menuGroup.Id,
Name = menuGroup.Name
})
.ToList();
}
}

View file

@ -3654,6 +3654,12 @@
"en": "The maximum number of simultaneous users has been reached.",
"tr": "Eş zamanlı kullanıcı limiti dolmuştur."
},
{
"resourceName": "Platform",
"key": "Abp.Identity.BranchLimitError",
"en": "The maximum number of active branches has been reached.",
"tr": "Aktif şube limiti dolmuştur."
},
{
"resourceName": "Platform",
"key": "Abp.Identity.IpRestrictionError",
@ -19931,6 +19937,12 @@
"key": "MessengerWidget.MessageDeleteFailed",
"en": "Message could not be deleted",
"tr": "Mesaj silinemedi"
},
{
"resourceName": "Platform",
"key": "App.Tenant.Create",
"en": "Tenant Create",
"tr": "Tenant Oluştur"
}
]
}

View file

@ -93,7 +93,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
EditingOptionJson = DefaultEditingOptionJson(TenantManagementPermissions.Tenants.Default, 950, 750, true, true, true, true, false, true),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>()
{
new() { Order=1, ColCount=3, ColSpan=1, ItemType="group", Items =
new() { Order=1, ColCount=4, ColSpan=1, ItemType="group", Items =
[
new EditingFormItemDto { Order=1, DataField = "Name", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
new EditingFormItemDto { Order=2, DataField = "OrganizationName", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
@ -104,20 +104,20 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
new EditingFormItemDto { Order=7, DataField = "PhoneNumber", ColSpan=1, EditorType2=EditorTypes.dxTextBox, EditorOptions=EditorOptionValues.PhoneEditorOptions },
new EditingFormItemDto { Order=8, DataField = "FaxNumber", ColSpan=1, EditorType2=EditorTypes.dxTextBox, EditorOptions=EditorOptionValues.PhoneEditorOptions },
new EditingFormItemDto { Order=9, DataField = "MenuGroup", ColSpan=1, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order=10, DataField = "Email", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
new EditingFormItemDto { Order=11, DataField = "Website", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
new EditingFormItemDto { Order=12, DataField = "IsActive", ColSpan=1, EditorType2=EditorTypes.dxCheckBox },
]
},
new() { Order=2, ColCount=3, ColSpan=1, ItemType="group", Items =
new() { Order=2, ColCount=4, ColSpan=1, ItemType="group", Items =
[
new EditingFormItemDto { Order=1, DataField = "Country", ColSpan=1, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order=2, DataField = "City", ColSpan=1, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order=3, DataField = "District", ColSpan=1, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order=4, DataField = "Township", ColSpan=1, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order=5, DataField = "PostalCode", ColSpan=1, EditorType2=EditorTypes.dxTextBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order=6, DataField = "Email", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
new EditingFormItemDto { Order=7, DataField = "Website", ColSpan=1, EditorType2=EditorTypes.dxTextBox },
new EditingFormItemDto { Order=8, DataField = "IsActive", ColSpan=1, EditorType2=EditorTypes.dxCheckBox },
new EditingFormItemDto { Order=9, DataField = "Address1", ColSpan=3, EditorType2=EditorTypes.dxTextArea },
new EditingFormItemDto { Order=10, DataField = "Address2", ColSpan=3, EditorType2=EditorTypes.dxTextArea },
new EditingFormItemDto { Order=6, DataField = "Address1", ColSpan=3, EditorType2=EditorTypes.dxTextArea },
new EditingFormItemDto { Order=7, DataField = "Address2", ColSpan=4, EditorType2=EditorTypes.dxTextArea },
]
}
}),
@ -6963,6 +6963,19 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
PagerOptionJson = DefaultPagerOptionJson,
EditingOptionJson = DefaultEditingOptionJson(listFormName, 1200, 700, true, true, true, true, false, true),
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
new() {
Hint = "Tenant",
Text = "Tenant",
AuthName = TenantManagementPermissions.Tenants.Create,
DialogName = "CreateTenantFromOrderDialog",
DialogParameters = JsonSerializer.Serialize(new {
orderId = "@Id"
}),
IsVisible = true,
VisibleExpression = "(e) => !e.row?.data?.TenantId",
},
}),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
{
new() { Order=1, ColCount=4, ColSpan=1, ItemType="group", Items =

View file

@ -509,6 +509,128 @@
"IsDisabled": false,
"ShortName": "Sas"
},
{
"ParentCode": "App.Saas",
"Code": "App.Public",
"DisplayName": "App.Public",
"Order": 0,
"Url": null,
"Icon": "FcTemplate",
"RequiredPermissionName": null,
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Home",
"DisplayName": "App.Home",
"Order": 0,
"Url": "/admin/public/home/designer",
"Icon": "FcHome",
"RequiredPermissionName": "App.Home",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.About",
"DisplayName": "App.About",
"Order": 1,
"Url": "/admin/public/about/designer",
"Icon": "FcAbout",
"RequiredPermissionName": "App.About",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Services",
"DisplayName": "App.Services",
"Order": 2,
"Url": "/admin/public/services/designer",
"Icon": "FcServices",
"RequiredPermissionName": "App.Services",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.Products",
"DisplayName": "App.Orders.Products",
"Order": 3,
"Url": "/admin/list/App.Orders.Products",
"Icon": "FcDiploma1",
"RequiredPermissionName": "App.Orders.Products",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.PaymentMethods",
"DisplayName": "App.Orders.PaymentMethods",
"Order": 4,
"Url": "/admin/list/App.Orders.PaymentMethods",
"Icon": "FcFeedIn",
"RequiredPermissionName": "App.Orders.PaymentMethods",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.InstallmentOptions",
"DisplayName": "App.Orders.InstallmentOptions",
"Order": 5,
"Url": "/admin/list/App.Orders.InstallmentOptions",
"Icon": "FcProcess",
"RequiredPermissionName": "App.Orders.InstallmentOptions",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.SalesOrders",
"DisplayName": "App.Orders.SalesOrders",
"Order": 6,
"Url": "/admin/list/App.Orders.SalesOrders",
"Icon": "FcCollect",
"RequiredPermissionName": "App.Orders.SalesOrders",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Category",
"DisplayName": "App.BlogManagement.Category",
"Order": 7,
"Url": "/admin/list/App.BlogManagement.Category",
"Icon": "FaCertificate",
"RequiredPermissionName": "App.BlogManagement.Category",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Posts",
"DisplayName": "App.BlogManagement.Posts",
"Order": 8,
"Url": "/admin/list/App.BlogManagement.Posts",
"Icon": "FaWeixin",
"RequiredPermissionName": "App.BlogManagement.Posts",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Demos",
"DisplayName": "App.Demos",
"Order": 9,
"Url": "/admin/list/App.Demos",
"Icon": "FcMissedCall",
"RequiredPermissionName": "App.Demos",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Contact",
"DisplayName": "App.Contact",
"Order": 10,
"Url": "/admin/public/contact/designer",
"Icon": "FcContacts",
"RequiredPermissionName": "App.Contact",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "AbpTenantManagement.Tenants",
@ -780,131 +902,11 @@
"RequiredPermissionName": "App.BackgroundWorkers.Jobs",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Public",
"DisplayName": "App.Public",
"Order": 12,
"Url": null,
"Icon": "FcTemplate",
"RequiredPermissionName": null,
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Home",
"DisplayName": "App.Home",
"Order": 0,
"Url": "/admin/public/home/designer",
"Icon": "FcHome",
"RequiredPermissionName": "App.Home",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.About",
"DisplayName": "App.About",
"Order": 1,
"Url": "/admin/public/about/designer",
"Icon": "FcAbout",
"RequiredPermissionName": "App.About",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Services",
"DisplayName": "App.Services",
"Order": 2,
"Url": "/admin/public/services/designer",
"Icon": "FcServices",
"RequiredPermissionName": "App.Services",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.Products",
"DisplayName": "App.Orders.Products",
"Order": 3,
"Url": "/admin/list/App.Orders.Products",
"Icon": "FcDiploma1",
"RequiredPermissionName": "App.Orders.Products",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.PaymentMethods",
"DisplayName": "App.Orders.PaymentMethods",
"Order": 4,
"Url": "/admin/list/App.Orders.PaymentMethods",
"Icon": "FcFeedIn",
"RequiredPermissionName": "App.Orders.PaymentMethods",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.InstallmentOptions",
"DisplayName": "App.Orders.InstallmentOptions",
"Order": 5,
"Url": "/admin/list/App.Orders.InstallmentOptions",
"Icon": "FcProcess",
"RequiredPermissionName": "App.Orders.InstallmentOptions",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Orders.SalesOrders",
"DisplayName": "App.Orders.SalesOrders",
"Order": 6,
"Url": "/admin/list/App.Orders.SalesOrders",
"Icon": "FcCollect",
"RequiredPermissionName": "App.Orders.SalesOrders",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Category",
"DisplayName": "App.BlogManagement.Category",
"Order": 7,
"Url": "/admin/list/App.BlogManagement.Category",
"Icon": "FaCertificate",
"RequiredPermissionName": "App.BlogManagement.Category",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.BlogManagement.Posts",
"DisplayName": "App.BlogManagement.Posts",
"Order": 8,
"Url": "/admin/list/App.BlogManagement.Posts",
"Icon": "FaWeixin",
"RequiredPermissionName": "App.BlogManagement.Posts",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Demos",
"DisplayName": "App.Demos",
"Order": 9,
"Url": "/admin/list/App.Demos",
"Icon": "FcMissedCall",
"RequiredPermissionName": "App.Demos",
"IsDisabled": false
},
{
"ParentCode": "App.Public",
"Code": "App.Contact",
"DisplayName": "App.Contact",
"Order": 10,
"Url": "/admin/public/contact/designer",
"Icon": "FcContacts",
"RequiredPermissionName": "App.Contact",
"IsDisabled": false
},
{
"ParentCode": "App.Saas",
"Code": "App.Menus",
"DisplayName": "App.Menus",
"Order": 13,
"Order": 12,
"Url": null,
"Icon": "FcParallelTasks",
"RequiredPermissionName": null,

View file

@ -1,6 +1,12 @@
import { PagedAndSortedResultRequestDto, PagedResultDto } from '@/proxy/abp'
import { MenuDto } from '@/proxy/menus/models'
import apiService, { Config } from '@/services/api.service'
import apiService from '@/services/api.service'
export type MenuGroupLookupDto = {
key: string
name: string
group?: string
}
export class MenuService {
apiName = 'Default'
@ -85,6 +91,15 @@ export class MenuService {
},
{ apiName: this.apiName },
)
getMenuGroups = () =>
apiService.fetchData<MenuGroupLookupDto[]>(
{
method: 'GET',
url: '/api/app/menu/menu-groups',
},
{ apiName: this.apiName },
)
}
export const getMenus = async (skipCount = 0, maxResultCount = 1000, sorting = 'order') => {
@ -96,3 +111,9 @@ export const getMenus = async (skipCount = 0, maxResultCount = 1000, sorting = '
maxResultCount,
})
}
export const getMenuGroups = async () => {
const menuService = new MenuService()
return await menuService.getMenuGroups()
}

View file

@ -3,6 +3,12 @@ import { SeedTenantDataInput } from '../proxy/admin/tenant/models'
import { CustomTenantDto, TenantDto } from '../proxy/config/models'
import apiService from './api.service'
export type CreateTenantFromOrderInput = {
orderId: string
name: string
menuGroup: string
}
export const getTenants = (skipCount = 0, maxResultCount = 10) =>
apiService.fetchData<PagedResultDto<TenantDto>>({
method: 'GET',
@ -53,4 +59,13 @@ export const postSeedTenantData = (data: SeedTenantDataInput) =>
data,
})
export const createTenantFromOrder = (data: CreateTenantFromOrderInput) =>
apiService.fetchData<string>({
method: 'POST',
url: '/api/app/list-form-dynamic-api/create-tenant-from-order',
data: {
data,
keys: [data.orderId],
listFormCode: 'App.Orders.SalesOrders',
},
})

View file

@ -0,0 +1,170 @@
import {
Button,
Dialog,
FormContainer,
FormItem,
Input,
Notification,
Select,
toast,
} from '@/components/ui'
import { getMenuGroups } from '@/services/menu.service'
import { createTenantFromOrder } from '@/services/tenant.service'
import { SelectBoxOption } from '@/types/shared'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik'
import { useEffect, useState } from 'react'
import * as Yup from 'yup'
type CreateTenantFromOrderValues = {
name: string
menuGroup: string
}
type CreateTenantFromOrderDialogProps = {
open: boolean
onDialogClose: () => void
orderId: string
}
const schema = Yup.object().shape({
name: Yup.string().trim().required(),
menuGroup: Yup.string().trim().required(),
})
const CreateTenantFromOrderDialog = ({
open,
onDialogClose,
orderId,
}: CreateTenantFromOrderDialogProps) => {
const { translate } = useLocalization()
const [menuGroupOptions, setMenuGroupOptions] = useState<SelectBoxOption[]>([])
const [isMenuGroupsLoading, setIsMenuGroupsLoading] = useState(false)
useEffect(() => {
if (!open) {
return
}
const fetchMenuGroups = async () => {
setIsMenuGroupsLoading(true)
try {
const response = await getMenuGroups()
const items = response?.data ?? []
setMenuGroupOptions(
items.map((item: any) => ({
value: String(item.key ?? item.Key ?? ''),
label: String(item.name ?? item.Name ?? ''),
})),
)
} catch {
setMenuGroupOptions([])
} finally {
setIsMenuGroupsLoading(false)
}
}
fetchMenuGroups()
}, [open])
const handleSubmit = async (
values: CreateTenantFromOrderValues,
{ setSubmitting }: FormikHelpers<CreateTenantFromOrderValues>,
) => {
setSubmitting(true)
try {
await createTenantFromOrder({
orderId,
name: values.name.trim(),
menuGroup: values.menuGroup.trim(),
})
toast.push(
<Notification type="success" duration={2500}>
{translate('::App.Platform.SaveSuccess') || 'Tenant kaydedildi'}
</Notification>,
{ placement: 'top-end' },
)
onDialogClose()
} catch (error) {
const message =
(error as any)?.response?.data?.error?.message ??
(error as any)?.response?.data?.message ??
(error as any)?.message ??
'Islem basarisiz'
toast.push(
<Notification type="danger" duration={5000}>
{message}
</Notification>,
{ placement: 'top-end' },
)
} finally {
setSubmitting(false)
}
}
return (
<Dialog isOpen={open} onClose={onDialogClose} onRequestClose={onDialogClose}>
<h5 className="mb-4">{translate('::App.Tenant.Create')}</h5>
<Formik<CreateTenantFromOrderValues>
initialValues={{
name: '',
menuGroup: 'Erp',
}}
validationSchema={schema}
onSubmit={handleSubmit}
>
{({ errors, touched, isSubmitting }) => (
<Form>
<FormContainer>
<FormItem
label="Menu Group"
invalid={Boolean(errors.menuGroup && touched.menuGroup)}
errorMessage={errors.menuGroup}
>
<Field name="menuGroup">
{({ field, form }: FieldProps<string>) => (
<Select
field={field}
form={form}
isClearable={true}
isLoading={isMenuGroupsLoading}
options={menuGroupOptions}
value={menuGroupOptions.filter((option) => option.value === field.value)}
onChange={(option) => form.setFieldValue(field.name, option?.value ?? '')}
/>
)}
</Field>
</FormItem>
<FormItem
label="Tenant Name"
invalid={Boolean(errors.name && touched.name)}
errorMessage={errors.name}
>
<Field name="name" component={Input} />
</FormItem>
<div className="flex justify-end gap-2 mt-6">
<Button type="button" variant="plain" onClick={onDialogClose}>
{translate('::Cancel')}
</Button>
<Button variant="solid" loading={isSubmitting} type="submit">
{translate('::Confirm')}
</Button>
</div>
</FormContainer>
</Form>
)}
</Formik>
</Dialog>
)
}
export default CreateTenantFromOrderDialog

View file

@ -1,4 +1,5 @@
import TenantsConnectionString from '@/views/admin/tenant-management/TenantsConnectionString'
import CreateTenantFromOrderDialog from '@/views/admin/tenant-management/CreateTenantFromOrderDialog'
import { useDialogContext } from './DialogProvider'
import CreateNotification from '@/views/admin/notification/CreateNotification'
import AuditLogDetail from '@/views/admin/auditLog/AuditLogDetail'
@ -42,6 +43,14 @@ const DialogShowComponent = (): JSX.Element => {
{...dialogContext.config?.props}
></TenantsConnectionString>
)
case 'CreateTenantFromOrderDialog':
return (
<CreateTenantFromOrderDialog
open={true}
onDialogClose={handleDialogClose}
{...dialogContext.config?.props}
></CreateTenantFromOrderDialog>
)
case 'CreateNotification':
return (
<CreateNotification