From 4bac59f322378c6b1c97f199b66b55321434e68e Mon Sep 17 00:00:00 2001 From: Alexandr Sulimov Date: Fri, 23 Jun 2023 09:03:00 +0300 Subject: [PATCH] update --- MyOffice.Data.Models/Items/Item.cs | 3 + .../Account/IMotionRepository.cs | 3 + .../Account/MotionRepository.cs | 19 +++ MyOffice.SPA/src/app/core/core.module.ts | 6 +- .../{account.motion.ts => motion.model.ts} | 2 +- .../app/pages/accounts/account.component.html | 9 +- .../app/pages/accounts/account.component.ts | 40 +++---- .../accounts/account.list.component.html | 2 +- .../pages/accounts/account.list.component.ts | 9 +- .../app/pages/accounts/motion.component.html | 23 ++-- .../app/pages/accounts/motion.component.ts | 91 +++++++++++---- .../src/app/pages/pages-routing.module.ts | 4 + MyOffice.SPA/src/app/pages/pages.module.ts | 2 +- .../account/account.category.component.ts | 2 +- .../settings/item/item.category.component.ts | 2 +- .../app/pages/settings/item/item.component.ts | 2 +- MyOffice.Services/Account/AccountService.cs | 108 +++++++++++++----- .../Account/Domain/MotionAddResult.cs | 2 +- .../{MotionAdd.cs => MotionAddUpdate.cs} | 2 +- .../Account/Domain/MotionDeleteResult.cs | 8 ++ .../Account/Domain/MotionUpdateResult.cs | 8 ++ .../Item/Domain/ItemGetOrAddResult.cs | 10 ++ MyOffice.Services/Item/ItemService.cs | 93 ++++++++++++--- MyOffice.Web/Controllers/AccountController.cs | 44 ++++++- ...tMotionsGetModel.cs => MotionsGetModel.cs} | 2 +- MyOffice.Web/Models/Motion/MotionRequest.cs | 4 +- MyOffice.Web/Models/Motion/MotionViewModel.cs | 2 +- 27 files changed, 376 insertions(+), 126 deletions(-) rename MyOffice.SPA/src/app/model/{account.motion.ts => motion.model.ts} (73%) rename MyOffice.Services/Account/Domain/{MotionAdd.cs => MotionAddUpdate.cs} (89%) create mode 100644 MyOffice.Services/Account/Domain/MotionDeleteResult.cs create mode 100644 MyOffice.Services/Account/Domain/MotionUpdateResult.cs create mode 100644 MyOffice.Services/Item/Domain/ItemGetOrAddResult.cs rename MyOffice.Web/Models/Account/{AccountMotionsGetModel.cs => MotionsGetModel.cs} (84%) diff --git a/MyOffice.Data.Models/Items/Item.cs b/MyOffice.Data.Models/Items/Item.cs index d36014b..44ec021 100644 --- a/MyOffice.Data.Models/Items/Item.cs +++ b/MyOffice.Data.Models/Items/Item.cs @@ -9,6 +9,9 @@ using MyOffice.Data.Models.Accounts; public class Item { public int Id { get; set; } + /// + /// UnCategorized category is CategoryId = UserId + /// public Guid CategoryId { get; set; } public ItemCategory Category { get; set; } = null!; public Guid ItemGlobalId { get; set; } diff --git a/MyOffice.Data.Repositories/Account/IMotionRepository.cs b/MyOffice.Data.Repositories/Account/IMotionRepository.cs index ee84372..ffb08b1 100644 --- a/MyOffice.Data.Repositories/Account/IMotionRepository.cs +++ b/MyOffice.Data.Repositories/Account/IMotionRepository.cs @@ -6,4 +6,7 @@ public interface IMotionRepository { bool Add(Motion motion); List GetByAccount(Guid accountId, DateTime dateFrom, DateTime dateTo); + Motion? Get(Guid userId, Guid id); + bool Update(Motion motion); + bool Remove(Motion motion); } \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Account/MotionRepository.cs b/MyOffice.Data.Repositories/Account/MotionRepository.cs index bcdc1ce..ef21da6 100644 --- a/MyOffice.Data.Repositories/Account/MotionRepository.cs +++ b/MyOffice.Data.Repositories/Account/MotionRepository.cs @@ -21,4 +21,23 @@ public class MotionRepository : AppRepository, IMotionRepository .ThenByDescending(x => x.CreatedOn) .ToList(); } + + public Motion? Get(Guid userId, Guid id) + { + return _context + .Motions + .Include(x => x.Item) + .ThenInclude(x => x.ItemGlobal) + .FirstOrDefault(x => x.Account!.AccessRights!.Any(a => a.UserId == userId) && x.Id == id); + } + + public bool Update(Motion motion) + { + return UpdateBase(motion) > 0; + } + + public bool Remove(Motion motion) + { + return RemoveBase(motion) > 0; + } } \ No newline at end of file diff --git a/MyOffice.SPA/src/app/core/core.module.ts b/MyOffice.SPA/src/app/core/core.module.ts index 4ab0167..c1121af 100644 --- a/MyOffice.SPA/src/app/core/core.module.ts +++ b/MyOffice.SPA/src/app/core/core.module.ts @@ -1,5 +1,9 @@ // angular -import { NgModule, Optional, SkipSelf, CUSTOM_ELEMENTS_SCHEMA, APP_INITIALIZER } from '@angular/core'; +import { NgModule } from '@angular/core'; +import { Optional } from '@angular/core'; +import { SkipSelf } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { APP_INITIALIZER } from '@angular/core'; import { CommonModule } from '@angular/common'; // libs diff --git a/MyOffice.SPA/src/app/model/account.motion.ts b/MyOffice.SPA/src/app/model/motion.model.ts similarity index 73% rename from MyOffice.SPA/src/app/model/account.motion.ts rename to MyOffice.SPA/src/app/model/motion.model.ts index 8f42de4..5bcc33d 100644 --- a/MyOffice.SPA/src/app/model/account.motion.ts +++ b/MyOffice.SPA/src/app/model/motion.model.ts @@ -1,4 +1,4 @@ -export interface AccountMotionModel { +export interface MotionModel { id?: string; date?: Date; motion?: string; diff --git a/MyOffice.SPA/src/app/pages/accounts/account.component.html b/MyOffice.SPA/src/app/pages/accounts/account.component.html index eba1f9f..685e48d 100644 --- a/MyOffice.SPA/src/app/pages/accounts/account.component.html +++ b/MyOffice.SPA/src/app/pages/accounts/account.component.html @@ -1,4 +1,4 @@ - +

{{account.account.name}}

@@ -36,9 +36,12 @@ -
+
- +
diff --git a/MyOffice.SPA/src/app/pages/accounts/account.component.ts b/MyOffice.SPA/src/app/pages/accounts/account.component.ts index 15da865..82cc197 100644 --- a/MyOffice.SPA/src/app/pages/accounts/account.component.ts +++ b/MyOffice.SPA/src/app/pages/accounts/account.component.ts @@ -15,7 +15,7 @@ import * as moment from 'moment'; // app import { ApiRoutes } from '../../api-routes'; import { AccountDetailedModel } from '../../model/account.detailed.model'; -import { AccountMotionModel } from '../../model/account.motion'; +import { MotionModel } from '../../model/motion.model'; @Component({ templateUrl: './account.component.html', @@ -23,13 +23,13 @@ import { AccountMotionModel } from '../../model/account.motion'; selector: 'account' }) export class AccountComponent { - public motions?: AccountMotionModel[]; - public newMotion: AccountMotionModel; + public motions?: MotionModel[]; + public newMotion: MotionModel; public form!: UntypedFormGroup; @Input('account') account!: AccountDetailedModel; - @Input('expanded') expanded!: boolean; + @Input('active') active: boolean = false; - @Output() onUpdate: EventEmitter = new EventEmitter(); + @Output() onUpdate: EventEmitter = new EventEmitter(); constructor( private fb: UntypedFormBuilder, @@ -60,27 +60,18 @@ export class AccountComponent { onSubmitClick() { } - handlerOnAdd(accountMotion: AccountMotionModel) { + handlerOnAdd(motion: MotionModel) { this.loadMotions(); this.httpClient .get(ApiRoutes.Account.replace(':id', this.account.account!.id!)) .subscribe(data => { this.account = data; }); + } - /*var md = moment(accountMotion.date); - var mdf = moment(this.form.value.dateFrom); - var mdt = moment(this.form.value.dateTo); - if (md.isBetween(mdf, mdt, 'days', '[]')) { - this.motions?.push(accountMotion); - //this.motions?.sort((a, b) => (b.date!.getMilliseconds() - a.date!.getMilliseconds())); - this.motions?.sort((a, b) => { - var aa = moment(a.date).toDate(); - var bb = moment(b.date).toDate(); - - return (bb.getMilliseconds() - aa.getMilliseconds()); - }); - }*/ + handlerOnDelete(motion: MotionModel) { + const index = this.motions!.findIndex(x => x.id === motion.id); + this.motions!.splice(index, 1); } private loadMotions() { @@ -90,10 +81,19 @@ export class AccountComponent { this.activatedRoute.params.subscribe(params => { this.httpClient - .get(url) + .get(url) .subscribe(data => { this.motions = data; }); }); } + + afterExpand() { + var refresh = window.location.protocol + "//"; + refresh += window.location.host; + refresh += window.location.pathname; + refresh += window.location.hash; + refresh += '/account/' + this.account.account.id; + window.history.pushState({ path: refresh }, '', refresh); + } } diff --git a/MyOffice.SPA/src/app/pages/accounts/account.list.component.html b/MyOffice.SPA/src/app/pages/accounts/account.list.component.html index cf3134c..0f4121a 100644 --- a/MyOffice.SPA/src/app/pages/accounts/account.list.component.html +++ b/MyOffice.SPA/src/app/pages/accounts/account.list.component.html @@ -9,7 +9,7 @@
- +
diff --git a/MyOffice.SPA/src/app/pages/accounts/account.list.component.ts b/MyOffice.SPA/src/app/pages/accounts/account.list.component.ts index eb62c71..dc9f581 100644 --- a/MyOffice.SPA/src/app/pages/accounts/account.list.component.ts +++ b/MyOffice.SPA/src/app/pages/accounts/account.list.component.ts @@ -4,18 +4,11 @@ import { HttpClient } from '@angular/common/http'; import { ActivatedRoute } from '@angular/router'; // libs -import Swal from 'sweetalert2'; -import { MatDialog } from '@angular/material/dialog'; // app import { AccountCategoryService } from '../../services/account.category.service'; import { ApiRoutes } from '../../api-routes'; -import { AccountCategoryModel } from '../../model/account.category.model'; -import { SettingsAccountAddComponent } from '../settings/account/add.account.component'; -import { SettingsAccountEditComponent } from '../settings/account/edit.account.component'; -import { AccountModel } from '../../model/account.model'; import { AccountDetailedModel } from '../../model/account.detailed.model'; -import { AccountMotionModel } from '../../model/account.motion'; @Component({ templateUrl: './account.list.component.html', @@ -24,12 +17,14 @@ import { AccountMotionModel } from '../../model/account.motion'; export class AccountListComponent { public accounts?: AccountDetailedModel[]; public category = ''; + public activeAccount = ''; constructor( private httpClient: HttpClient, private activatedRoute: ActivatedRoute, private accountCategoryService: AccountCategoryService, ) { + this.activatedRoute.params.subscribe(x => this.activeAccount = x['accountId']); } ngOnInit(): void { diff --git a/MyOffice.SPA/src/app/pages/accounts/motion.component.html b/MyOffice.SPA/src/app/pages/accounts/motion.component.html index 402ce31..6d62e2b 100644 --- a/MyOffice.SPA/src/app/pages/accounts/motion.component.html +++ b/MyOffice.SPA/src/app/pages/accounts/motion.component.html @@ -1,4 +1,4 @@ -
+
@@ -42,19 +42,24 @@
- - - +
-
+
diff --git a/MyOffice.SPA/src/app/pages/accounts/motion.component.ts b/MyOffice.SPA/src/app/pages/accounts/motion.component.ts index b479297..cf9522c 100644 --- a/MyOffice.SPA/src/app/pages/accounts/motion.component.ts +++ b/MyOffice.SPA/src/app/pages/accounts/motion.component.ts @@ -12,11 +12,12 @@ import { ElementRef } from '@angular/core'; // libs import * as moment from 'moment'; +import Swal from 'sweetalert2'; // app import { ApiRoutes } from '../../api-routes'; import { AccountModel } from '../../model/account.model'; -import { AccountMotionModel } from '../../model/account.motion'; +import { MotionModel } from '../../model/motion.model'; import { atLeastOneNumber } from '../../core/validators/atleastonenumber.validator'; @Component({ @@ -28,10 +29,11 @@ export class MotionComponent { public form!: FormGroup; public errorMessage?: string; - @Input('motion') motion!: AccountMotionModel; + @Input('motion') motion!: MotionModel; @Input('account') account!: AccountModel; - @Output() onAdd: EventEmitter = new EventEmitter(); + @Output() onAdd: EventEmitter = new EventEmitter(); + @Output() onDelete: EventEmitter = new EventEmitter(); @ViewChild('motionInput') motionInput?: ElementRef; @@ -68,28 +70,75 @@ export class MotionComponent { }); } - onSubmitClick() { + add() { this.form.markAllAsTouched(); - if (this.form.valid) { - this.httpClient - .post(ApiRoutes.Motions.replace(':id', this.account.id!), this.form.value) - .subscribe(response => { - if (!this.form.value.id) { - this.onAdd?.emit(response); - this.form.patchValue({ - motion: '', - plus: 0, - minus: 0, - }); - this.form.markAsUntouched(); + this.httpClient + .post(ApiRoutes.Motions.replace(':id', this.account.id!), this.form.value) + .subscribe(response => { + this.onAdd?.emit(response); - this.motionInput?.nativeElement.focus(); - } - }, error => { - this.errorMessage = error.detail; + this.form.patchValue({ + motion: '', + plus: 0, + minus: 0, }); - } + this.form.markAsUntouched(); + + this.motionInput?.nativeElement.focus(); + }, error => { + this.errorMessage = error.detail; + }); + } + + update() { + var url = ApiRoutes.Motion + .replace(':id', this.account.id!) + .replace(':motionId', this.motion.id!); + + this.httpClient + .put(url, this.form.value) + .subscribe(response => { + this.form.markAsUntouched(); + }, error => { + this.errorMessage = error.detail; + }); + } + + delete() { + Swal.fire({ + title: 'Delete motion ' + this.motion.motion, + showCancelButton: true, + confirmButtonText: 'Delete', + showLoaderOnConfirm: true, + preConfirm: (name) => { + return new Promise((resolve, reject) => { + var url = ApiRoutes.Motion + .replace(':id', this.account.id!) + .replace(':motionId', this.motion.id!); + + this.httpClient.delete(url) + .subscribe(data => { + resolve(data); + }, error => { + Swal.showValidationMessage(error.detail); + reject(); + }); + + }).catch(x => { + return false; + }); + }, + allowOutsideClick: () => !Swal.isLoading(), + }).then((result) => { + if (result.isConfirmed) { + this.onDelete?.emit((result.value! as MotionModel)); + } + }); + } + + import() { + } addDay(days: number) { diff --git a/MyOffice.SPA/src/app/pages/pages-routing.module.ts b/MyOffice.SPA/src/app/pages/pages-routing.module.ts index 8e4d427..9341c68 100644 --- a/MyOffice.SPA/src/app/pages/pages-routing.module.ts +++ b/MyOffice.SPA/src/app/pages/pages-routing.module.ts @@ -42,6 +42,10 @@ const routes: Routes = [ path: 'account-category/:id', component: AccountListComponent, }, + { + path: 'account-category/:id/account/:accountId', + component: AccountListComponent, + }, ]; @NgModule({ diff --git a/MyOffice.SPA/src/app/pages/pages.module.ts b/MyOffice.SPA/src/app/pages/pages.module.ts index 69632c7..04f13ac 100644 --- a/MyOffice.SPA/src/app/pages/pages.module.ts +++ b/MyOffice.SPA/src/app/pages/pages.module.ts @@ -79,7 +79,7 @@ import { MotionComponent } from './accounts/motion.component'; MatCardModule, MatExpansionModule, NgxMaskModule, - NgxCurrencyModule, + NgxCurrencyModule ], providers: [ { provide: MAT_DATE_LOCALE, useValue: 'en-GB' }, diff --git a/MyOffice.SPA/src/app/pages/settings/account/account.category.component.ts b/MyOffice.SPA/src/app/pages/settings/account/account.category.component.ts index fbb9739..f6407b6 100644 --- a/MyOffice.SPA/src/app/pages/settings/account/account.category.component.ts +++ b/MyOffice.SPA/src/app/pages/settings/account/account.category.component.ts @@ -96,7 +96,7 @@ export class SettingsAccountCategoryComponent { public remove(category: AccountCategoryModel) { Swal.fire({ - title: 'Remove account category ' + category.name, + title: 'Delete account category ' + category.name, showCancelButton: true, confirmButtonText: 'Delete', showLoaderOnConfirm: true, diff --git a/MyOffice.SPA/src/app/pages/settings/item/item.category.component.ts b/MyOffice.SPA/src/app/pages/settings/item/item.category.component.ts index 73b5a40..18ccac5 100644 --- a/MyOffice.SPA/src/app/pages/settings/item/item.category.component.ts +++ b/MyOffice.SPA/src/app/pages/settings/item/item.category.component.ts @@ -96,7 +96,7 @@ export class SettingsItemCategoryComponent { public remove(category: ItemCategoryModel) { Swal.fire({ - title: 'Remove item category ' + category.name, + title: 'Delete item category ' + category.name, showCancelButton: true, confirmButtonText: 'Delete', showLoaderOnConfirm: true, diff --git a/MyOffice.SPA/src/app/pages/settings/item/item.component.ts b/MyOffice.SPA/src/app/pages/settings/item/item.component.ts index 0b5a325..62e7db5 100644 --- a/MyOffice.SPA/src/app/pages/settings/item/item.component.ts +++ b/MyOffice.SPA/src/app/pages/settings/item/item.component.ts @@ -72,7 +72,7 @@ export class SettingsItemComponent { public remove(category: ItemModel) { Swal.fire({ - title: 'Remove item from ' + category.name, + title: 'Delete item from ' + category.name, showCancelButton: true, confirmButtonText: 'Delete', showLoaderOnConfirm: true, diff --git a/MyOffice.Services/Account/AccountService.cs b/MyOffice.Services/Account/AccountService.cs index 3cdc6d1..77f966c 100644 --- a/MyOffice.Services/Account/AccountService.cs +++ b/MyOffice.Services/Account/AccountService.cs @@ -8,6 +8,8 @@ using Data.Repositories.Account; using Data.Repositories.Currency; using Data.Repositories.Item; + using Item; + using Item.Domain; using Microsoft.Extensions.Logging; using MyOffice.Services.Account.Domain; @@ -20,7 +22,8 @@ private readonly IAccountAccountCategoryRepository _accountAccountCategoryRepository; private readonly IMotionRepository _motionRepository; private readonly IItemRepository _itemRepository; - private readonly IItemGlobalRepository _motionGlobalRepository; + private readonly IItemGlobalRepository _itemGlobalRepository; + private readonly ItemService _itemService; public AccountService( ILogger logger, @@ -30,7 +33,8 @@ IAccountAccountCategoryRepository accountAccountCategoryRepository, IMotionRepository motionRepository, IItemRepository itemRepository, - IItemGlobalRepository motionGlobalRepository + IItemGlobalRepository itemGlobalRepository, + ItemService itemService ) { _logger = logger; @@ -40,7 +44,8 @@ _accountAccountCategoryRepository = accountAccountCategoryRepository; _motionRepository = motionRepository; _itemRepository = itemRepository; - _motionGlobalRepository = motionGlobalRepository; + _itemGlobalRepository = itemGlobalRepository; + _itemService = itemService; } public List GetAllCategories(Guid userId) @@ -282,7 +287,7 @@ public Exec MotionAdd( Guid userId, Guid accountId, - MotionAdd motion + MotionAddUpdate motion ) { if (motion == null) @@ -298,31 +303,10 @@ return result.Set(MotionAddResult.account_not_found); } - var motionGlobal = _motionGlobalRepository.GetByName(motion.Motion); - if (motionGlobal == null) + var itemExec = _itemService.GetOrCreate(userId, motion.Motion); + if (itemExec.Status != ItemGetOrAddResult.success) { - // add global motion - motionGlobal = new ItemGlobal - { - Id = Guid.NewGuid(), - Name = motion.Motion.Trim(), - }; - if (!_motionGlobalRepository.Add(motionGlobal)) - { - return result.Set(MotionAddResult.failure); - } - } - - var item = _itemRepository.GetByGlobal(userId, motionGlobal.Id); - if (item == null) - { - // add item - item = new Item - { - CategoryId = userId, - ItemGlobalId = motionGlobal.Id, - }; - _itemRepository.Add(item); + return result.Set(MotionAddResult.failure); } var motionDb = new Motion @@ -331,7 +315,7 @@ CreatedOn = DateTime.UtcNow, DateTime = motion.Date, AccountId = account.Id, - ItemId = item.Id, + ItemId = itemExec.Result!.Id, AmountPlus = motion.Plus, AmountMinus = motion.Minus, Description = motion.Description, @@ -343,12 +327,52 @@ } - item.ItemGlobal = motionGlobal; - motionDb.Item = item; + motionDb.Item = itemExec.Result!; return result.Set(motionDb); } + public Exec MotionUpdate( + Guid userId, + Guid accountId, + Guid motionId, + MotionAddUpdate motion + ) + { + if (motion == null) + throw new ArgumentNullException(nameof(motion)); + if (motion.Motion == null) + throw new ArgumentNullException(nameof(motion.Motion)); + + var result = new Exec(MotionUpdateResult.success); + + var exists = _motionRepository.Get(userId, motionId); + if (exists == null || exists.AccountId != accountId) + { + return result.Set(MotionUpdateResult.not_found); + } + + var itemExec = _itemService.GetOrCreate(userId, motion.Motion); + if (itemExec.Status != ItemGetOrAddResult.success) + { + return result.Set(MotionUpdateResult.failure); + } + + exists.Item.Id = itemExec.Result!.Id; + exists.DateTime = motion.Date; + exists.Description = motion.Description; + exists.AmountPlus = motion.Plus; + exists.AmountMinus = motion.Minus; + + if (!_motionRepository.Update(exists)) + { + return result.Set(MotionUpdateResult.failure); + + } + + return result.Set(exists); + } + public Exec, GeneralExecStatus> GetMotions( Guid userId, Guid accountId, @@ -368,5 +392,27 @@ return result.Set(motions); } + + public Exec MotionRemove( + Guid userId, + Guid accountId, + Guid motionId + ) + { + var result = new Exec(MotionDeleteResult.success); + + var exists = _motionRepository.Get(userId, motionId); + if (exists == null || exists.AccountId != accountId) + { + return result.Set(MotionDeleteResult.not_found); + } + + if (!_motionRepository.Remove(exists)) + { + return result.Set(MotionDeleteResult.failure); + } + + return result.Set(exists); + } } } diff --git a/MyOffice.Services/Account/Domain/MotionAddResult.cs b/MyOffice.Services/Account/Domain/MotionAddResult.cs index beb94e2..c693208 100644 --- a/MyOffice.Services/Account/Domain/MotionAddResult.cs +++ b/MyOffice.Services/Account/Domain/MotionAddResult.cs @@ -5,4 +5,4 @@ public enum MotionAddResult success, failure, account_not_found, -} +} \ No newline at end of file diff --git a/MyOffice.Services/Account/Domain/MotionAdd.cs b/MyOffice.Services/Account/Domain/MotionAddUpdate.cs similarity index 89% rename from MyOffice.Services/Account/Domain/MotionAdd.cs rename to MyOffice.Services/Account/Domain/MotionAddUpdate.cs index be3b0ab..4759abc 100644 --- a/MyOffice.Services/Account/Domain/MotionAdd.cs +++ b/MyOffice.Services/Account/Domain/MotionAddUpdate.cs @@ -1,6 +1,6 @@ namespace MyOffice.Services.Account.Domain { - public class MotionAdd + public class MotionAddUpdate { public DateTime Date { get; set; } public string Motion { get; set; } = null!; diff --git a/MyOffice.Services/Account/Domain/MotionDeleteResult.cs b/MyOffice.Services/Account/Domain/MotionDeleteResult.cs new file mode 100644 index 0000000..b141dbe --- /dev/null +++ b/MyOffice.Services/Account/Domain/MotionDeleteResult.cs @@ -0,0 +1,8 @@ +namespace MyOffice.Services.Account.Domain; + +public enum MotionDeleteResult +{ + success, + failure, + not_found, +} \ No newline at end of file diff --git a/MyOffice.Services/Account/Domain/MotionUpdateResult.cs b/MyOffice.Services/Account/Domain/MotionUpdateResult.cs new file mode 100644 index 0000000..b45f98d --- /dev/null +++ b/MyOffice.Services/Account/Domain/MotionUpdateResult.cs @@ -0,0 +1,8 @@ +namespace MyOffice.Services.Account.Domain; + +public enum MotionUpdateResult +{ + success, + failure, + not_found, +} \ No newline at end of file diff --git a/MyOffice.Services/Item/Domain/ItemGetOrAddResult.cs b/MyOffice.Services/Item/Domain/ItemGetOrAddResult.cs new file mode 100644 index 0000000..f3a22b0 --- /dev/null +++ b/MyOffice.Services/Item/Domain/ItemGetOrAddResult.cs @@ -0,0 +1,10 @@ +namespace MyOffice.Services.Item.Domain +{ + public enum ItemGetOrAddResult + { + success, + failure, + not_found, + accounts_exists, + } +} diff --git a/MyOffice.Services/Item/ItemService.cs b/MyOffice.Services/Item/ItemService.cs index 840a5d3..2b82672 100644 --- a/MyOffice.Services/Item/ItemService.cs +++ b/MyOffice.Services/Item/ItemService.cs @@ -3,29 +3,35 @@ using System; using System.Collections.Generic; using System.Linq; + using System.Xml.Linq; using Domain; using MyOffice.Core; + using MyOffice.Data.Models.Accounts; using MyOffice.Data.Models.Items; using MyOffice.Data.Repositories.Item; + using MyOffice.Services.Account.Domain; public class ItemService { - private readonly IItemCategoryRepository _motionCategoryRepository; - private readonly IItemRepository _motionRepository; + private readonly IItemCategoryRepository _itemCategoryRepository; + private readonly IItemRepository _itemRepository; + private readonly IItemGlobalRepository _itemGlobalRepository; public ItemService( - IItemCategoryRepository motionCategoryRepository, - IItemRepository motionRepository + IItemCategoryRepository itemCategoryRepository, + IItemRepository itemRepository, + IItemGlobalRepository itemGlobalRepository ) { - _motionCategoryRepository = motionCategoryRepository; - _motionRepository = motionRepository; + _itemCategoryRepository = itemCategoryRepository; + _itemRepository = itemRepository; + _itemGlobalRepository = itemGlobalRepository; } public List GetAllCategories(Guid userId) { - var result = _motionCategoryRepository.GetAll(userId); + var result = _itemCategoryRepository.GetAll(userId); if (result.All(x => x.Id != userId)) { var category = new ItemCategory @@ -34,9 +40,9 @@ UserId = userId, Name = "UnCategorized", }; - _motionCategoryRepository.Add(category); + _itemCategoryRepository.Add(category); - result.Add(_motionCategoryRepository.Get(userId, userId)!); + result.Add(_itemCategoryRepository.Get(userId, userId)!); } return result; } @@ -51,7 +57,7 @@ category.Id = Guid.NewGuid(); category.UserId = userId; - if (!_motionCategoryRepository.Add(category)) + if (!_itemCategoryRepository.Add(category)) { return result.Set(GeneralExecStatus.failure); } @@ -66,7 +72,7 @@ var result = new Exec(GeneralExecStatus.success); - var exists = _motionCategoryRepository.Get(userId, id); + var exists = _itemCategoryRepository.Get(userId, id); if (exists == null) { return result.Set(GeneralExecStatus.not_found); @@ -74,7 +80,7 @@ exists.Name = category.Name; - if (!_motionCategoryRepository.Update(exists)) + if (!_itemCategoryRepository.Update(exists)) { return result.Set(GeneralExecStatus.failure); } @@ -86,7 +92,7 @@ { var result = new Exec(ItemCategoryRemoveResult.success); - var exists = _motionCategoryRepository.Get(userId, id); + var exists = _itemCategoryRepository.Get(userId, id); if (exists == null) { return result.Set(ItemCategoryRemoveResult.not_found); @@ -96,7 +102,7 @@ { return result.Set(ItemCategoryRemoveResult.accounts_exists); } - if (!_motionCategoryRepository.Remove(exists)) + if (!_itemCategoryRepository.Remove(exists)) { return result.Set(ItemCategoryRemoveResult.failure); } @@ -106,19 +112,19 @@ public List GetAll(Guid userId) { - return _motionRepository.GetAll(userId); + return _itemRepository.GetAll(userId); } public List GetByCategory(Guid userId, Guid categoryId) { - return _motionRepository.GetByCategory(userId, categoryId); + return _itemRepository.GetByCategory(userId, categoryId); } public Exec Update(Guid userId, Guid motionId, Guid categoryId) { var result = new Exec(GeneralExecStatus.success); - var motion = _motionRepository.GetByGlobal(userId, motionId); + var motion = _itemRepository.GetByGlobal(userId, motionId); if (motion == null) { return result.Set(GeneralExecStatus.not_found); @@ -126,9 +132,60 @@ motion.Category.Id = categoryId; //motion.CategoryId = categoryId; - _motionRepository.Update(motion); + _itemRepository.Update(motion); return result.Set(motion); } + + public Exec GetOrCreate(Guid userId, string name) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + var result = new Exec(ItemGetOrAddResult.success); + + var itemGlobal = _itemGlobalRepository.GetByName(name); + if (itemGlobal == null) + { + // add global motion + itemGlobal = new ItemGlobal + { + Id = Guid.NewGuid(), + Name = name.Trim(), + }; + + if (!_itemGlobalRepository.Add(itemGlobal)) + { + return result.Set(ItemGetOrAddResult.failure); + } + + return GetOrCreate(userId, itemGlobal); + } + + return GetOrCreate(userId, itemGlobal); + } + + private Exec GetOrCreate(Guid userId, ItemGlobal itemGlobal) + { + if (itemGlobal == null) + throw new ArgumentNullException(nameof(itemGlobal)); + + var result = new Exec(ItemGetOrAddResult.success); + + var item = _itemRepository.GetByGlobal(userId, itemGlobal.Id); + if (item == null) + { + // add item to UnCategorized category + item = new Item + { + CategoryId = userId, + ItemGlobalId = itemGlobal.Id, + }; + _itemRepository.Add(item); + } + + item.ItemGlobal = itemGlobal; + return result.Set(item); + } } } diff --git a/MyOffice.Web/Controllers/AccountController.cs b/MyOffice.Web/Controllers/AccountController.cs index 08f55aa..e84199e 100644 --- a/MyOffice.Web/Controllers/AccountController.cs +++ b/MyOffice.Web/Controllers/AccountController.cs @@ -7,8 +7,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Models.Account; using Models.Motion; -using MyOffice.Data.Models.Accounts; -using MyOffice.Web.Models.AccountMotion; using Services.Account; using Services.Account.Domain; @@ -59,7 +57,7 @@ public class AccountController : BaseApiController } [HttpGet("~/api/accounts/{id}/motions")] - public object AccountMotionsGet(string id, [FromQuery] AccountMotionsGetModel request) + public object MotionsGet(string id, [FromQuery] MotionsGetModel request) { var exec = _accountService.GetMotions(UserId, id!.AsGuid(), request.From.StartOfDay(), request.To.EndOfDay()); @@ -78,7 +76,7 @@ public class AccountController : BaseApiController } [HttpPost("~/api/accounts/{id}/motions")] - public object AccountsMotionsPost(string id, MotionRequest motion) + public object MotionsPost(string id, MotionRequest motion) { var exec = _accountService.MotionAdd(UserId, id.AsGuid(), motion.FromModel()); @@ -95,4 +93,42 @@ public class AccountController : BaseApiController throw new NotSupportedException(exec.Status.ToString()); } } + + [HttpPut("~/api/accounts/{id}/motions/{motionId}")] + public object MotionsPut(string id, string motionId, MotionRequest motion) + { + var exec = _accountService.MotionUpdate(UserId, id.AsGuid(), motionId.AsGuid(), motion.FromModel()); + + switch (exec.Status) + { + case MotionUpdateResult.not_found: + return ProblemBadRequest("Motion not found."); + case MotionUpdateResult.failure: + return ProblemBadRequest("Updating motion failed."); + case MotionUpdateResult.success: + return exec.Result!.ToModel(); + + default: + throw new NotSupportedException(exec.Status.ToString()); + } + } + + [HttpDelete("~/api/accounts/{id}/motions/{motionId}")] + public object MotionsDelete(string id, string motionId) + { + var exec = _accountService.MotionRemove(UserId, id.AsGuid(), motionId.AsGuid()); + + switch (exec.Status) + { + case MotionDeleteResult.not_found: + return ProblemBadRequest("Motion not found."); + case MotionDeleteResult.failure: + return ProblemBadRequest("Deliting motion failed."); + case MotionDeleteResult.success: + return exec.Result!.ToModel(); + + default: + throw new NotSupportedException(exec.Status.ToString()); + } + } } \ No newline at end of file diff --git a/MyOffice.Web/Models/Account/AccountMotionsGetModel.cs b/MyOffice.Web/Models/Account/MotionsGetModel.cs similarity index 84% rename from MyOffice.Web/Models/Account/AccountMotionsGetModel.cs rename to MyOffice.Web/Models/Account/MotionsGetModel.cs index 578237b..054142a 100644 --- a/MyOffice.Web/Models/Account/AccountMotionsGetModel.cs +++ b/MyOffice.Web/Models/Account/MotionsGetModel.cs @@ -2,7 +2,7 @@ { using System.ComponentModel.DataAnnotations; - public class AccountMotionsGetModel + public class MotionsGetModel { [Required] public DateTime From { get; set; } diff --git a/MyOffice.Web/Models/Motion/MotionRequest.cs b/MyOffice.Web/Models/Motion/MotionRequest.cs index 7217cf7..ab3d503 100644 --- a/MyOffice.Web/Models/Motion/MotionRequest.cs +++ b/MyOffice.Web/Models/Motion/MotionRequest.cs @@ -13,9 +13,9 @@ public class MotionRequest public static class MotionRequestExtension { - public static MotionAdd FromModel(this MotionRequest input) + public static MotionAddUpdate FromModel(this MotionRequest input) { - return new MotionAdd + return new MotionAddUpdate { Date = input.Date, Motion = input.Motion, diff --git a/MyOffice.Web/Models/Motion/MotionViewModel.cs b/MyOffice.Web/Models/Motion/MotionViewModel.cs index 8aef614..02079cf 100644 --- a/MyOffice.Web/Models/Motion/MotionViewModel.cs +++ b/MyOffice.Web/Models/Motion/MotionViewModel.cs @@ -1,4 +1,4 @@ -namespace MyOffice.Web.Models.AccountMotion +namespace MyOffice.Web.Models.Motion { using Core.Extensions; using Data.Models.Accounts;