Sales Order üzerinden Otomatik Tenant tanımlama
This commit is contained in:
parent
6dae9c4e94
commit
c42a8d2bd1
11 changed files with 489 additions and 154 deletions
|
|
@ -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; }
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue