@ -0,0 +1,12 @@ | |||
import { NgModule } from '@angular/core'; | |||
import { RouterModule, Routes } from '@angular/router'; | |||
import { BookIssueComponent } from './book-issue.component'; | |||
import { authGuard, permissionGuard } from '@abp/ng.core'; | |||
const routes: Routes = [{ path: '', component: BookIssueComponent,canActivate: [authGuard, permissionGuard] }]; | |||
@NgModule({ | |||
imports: [RouterModule.forChild(routes)], | |||
exports: [RouterModule] | |||
}) | |||
export class BookIssueRoutingModule { } |
@ -0,0 +1,97 @@ | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="row"> | |||
<div class="col col-md-6"> | |||
<h5 class="card-title"> | |||
{{ 'Book-Issue' | abpLocalization }} | |||
</h5> | |||
</div> | |||
<div class="text-end col col-md-6"> | |||
<!-- Add the "new book" button here --> | |||
<div class="text-lg-end pt-2"> | |||
<button id="create" class="btn btn-primary" type="button" (click)="createBookIssue()"> | |||
<i class="fa fa-plus me-1"></i> | |||
<span>{{ "New Book Issue" | abpLocalization }}</span> | |||
</button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<ngx-datatable [rows]="bookIssueList.items" [count]="bookIssueList.totalCount" [list]="list" default> | |||
<ngx-datatable-column | |||
[name]="'::Actions' | abpLocalization" | |||
[maxWidth]="150" | |||
[sortable]="false" | |||
> | |||
<ng-template let-row="row" ngx-datatable-cell-template> | |||
<div ngbDropdown container="body" class="d-inline-block"> | |||
<button | |||
class="btn btn-primary btn-sm dropdown-toggle" | |||
data-toggle="dropdown" | |||
aria-haspopup="true" | |||
ngbDropdownToggle | |||
> | |||
<i class="fa fa-cog me-1"></i>{{ '::Actions' | abpLocalization }} | |||
</button> | |||
<div ngbDropdownMenu> | |||
<button ngbDropdownItem (click)="delete(row.bookIssueId)"> | |||
{{ 'un Issue' | abpLocalization }} | |||
</button> | |||
</div> | |||
</div> | |||
</ng-template> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'Book Name' | abpLocalization" prop="bookName"></ngx-datatable-column> | |||
<ngx-datatable-column [name]="'Customer Name' | abpLocalization" prop="customerName"> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'Issue Date' | abpLocalization" prop="issueDate"> | |||
<ng-template let-row="row" ngx-datatable-cell-template> | |||
{{ row.issueDate | date }} | |||
</ng-template> | |||
</ngx-datatable-column> | |||
</ngx-datatable> | |||
</div> | |||
</div> | |||
<!-- Add the modal here --> | |||
<abp-modal [(visible)]="isModalOpen"> | |||
<ng-template #abpHeader> | |||
<h3> Book Issued </h3> | |||
</ng-template> | |||
<ng-template #abpBody> | |||
<form [formGroup]="form" (ngSubmit)="save()"> | |||
<div class="mt-2"> | |||
<label for="book-type">Book Name</label><span> * </span> | |||
<select class="form-control" id="book-type" formControlName="bookId"> | |||
<option [ngValue]="null">Select a book name</option> | |||
<option [ngValue]="book.id" *ngFor="let book of dropDownbook"> {{ book.name }}</option> | |||
</select> | |||
</div> | |||
<div class="mt-2"> | |||
<label for="customer-name">Customer Name</label><span> * </span> | |||
<select class="form-control" id="customer-name" formControlName="customerId"> | |||
<option [ngValue]="null">Select a customer name</option> | |||
<option [ngValue]="customer.id" *ngFor="let customer of dropDownCustomer"> {{ customer.firstName }} {{ customer.lastName}}</option> | |||
</select> | |||
</div> | |||
</form> | |||
</ng-template> | |||
<ng-template #abpFooter> | |||
<button type="button" class="btn btn-secondary" abpClose> | |||
{{ '::Close' | abpLocalization }} | |||
</button> | |||
<!--added save button--> | |||
<button class="btn btn-primary" (click)="save()" [disabled]="form.invalid"> | |||
<i class="fa fa-check mr-1"></i> | |||
{{ '::Save' | abpLocalization }} | |||
</button> | |||
</ng-template> | |||
</abp-modal> |
@ -0,0 +1,23 @@ | |||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
import { BookIssueComponent } from './book-issue.component'; | |||
describe('BookIssueComponent', () => { | |||
let component: BookIssueComponent; | |||
let fixture: ComponentFixture<BookIssueComponent>; | |||
beforeEach(async () => { | |||
await TestBed.configureTestingModule({ | |||
declarations: [BookIssueComponent] | |||
}) | |||
.compileComponents(); | |||
fixture = TestBed.createComponent(BookIssueComponent); | |||
component = fixture.componentInstance; | |||
fixture.detectChanges(); | |||
}); | |||
it('should create', () => { | |||
expect(component).toBeTruthy(); | |||
}); | |||
}); |
@ -0,0 +1,83 @@ | |||
import { Component, OnInit } from '@angular/core'; | |||
import { ListService, PagedResultDto } from '@abp/ng.core'; | |||
import { BookIssueDto, BookIssueListDto, BookIssueService } from '@proxy/book-issued'; | |||
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; | |||
import { BookDto, BookService } from '@proxy/books'; | |||
import { CustomerDto, CustomerService } from '@proxy/customers'; | |||
import { ConfirmationService,Confirmation } from '@abp/ng.theme.shared'; | |||
@Component({ | |||
selector: 'app-book-issue', | |||
templateUrl: './book-issue.component.html', | |||
styleUrl: './book-issue.component.scss', | |||
providers: [ListService] | |||
}) | |||
export class BookIssueComponent implements OnInit { | |||
isModalOpen = false; | |||
form:FormGroup; | |||
dropDownbook= {} as Array<BookDto>; | |||
dropDownCustomer= {} as Array<CustomerDto>; | |||
bookIssueList = { items: [], totalCount: 0 } as PagedResultDto<BookIssueListDto>; | |||
constructor(public readonly list: ListService, | |||
private bookIssuedService: BookIssueService, | |||
private bookService: BookService, | |||
private customerService: CustomerService, | |||
private fb: FormBuilder, | |||
private confirmation: ConfirmationService ) {} | |||
ngOnInit(): void { | |||
this.dropdowninitiale(); | |||
const bookStreamCreator = (query) => this.bookIssuedService.getList(query); | |||
this.list.hookToQuery(bookStreamCreator).subscribe((response) => { | |||
this.bookIssueList = response; | |||
}); | |||
} | |||
createBookIssue() { | |||
this.buildForm(); | |||
this.isModalOpen = true; | |||
} | |||
buildForm() { | |||
this.form = this.fb.group({ | |||
bookId: ['', Validators.required], | |||
customerId: ['', Validators.required], | |||
}); | |||
} | |||
save() { | |||
if (this.form.invalid) { | |||
return; | |||
} | |||
this.bookIssuedService.create(this.form.value).subscribe(() => { | |||
this.isModalOpen = false; | |||
this.form.reset(); | |||
this.list.get(); | |||
}); | |||
} | |||
dropdowninitiale(){ | |||
this.bookService.getBookDropDown().subscribe((response)=>{ | |||
this.dropDownbook = response; | |||
}); | |||
this.customerService.getcustomerDropDown().subscribe((response)=>{ | |||
this.dropDownCustomer = response; | |||
}); | |||
} | |||
delete(bookIssueId: number) { | |||
this.confirmation.warn('::AreYouSureToUnIssue', '::AreYouSure').subscribe((status) => { | |||
if (status === Confirmation.Status.confirm) { | |||
this.bookIssuedService.delete(bookIssueId).subscribe(() => this.list.get()); | |||
} | |||
}); | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
import { NgModule } from '@angular/core'; | |||
import { CommonModule } from '@angular/common'; | |||
import { BookIssueRoutingModule } from './book-issue-routing.module'; | |||
import { BookIssueComponent } from './book-issue.component'; | |||
import{SharedModule} from '../shared/shared.module'; | |||
@NgModule({ | |||
declarations: [ | |||
BookIssueComponent | |||
], | |||
imports: [ | |||
CommonModule, | |||
BookIssueRoutingModule, | |||
SharedModule | |||
] | |||
}) | |||
export class BookIssueModule { } |
@ -0,0 +1,12 @@ | |||
import { NgModule } from '@angular/core'; | |||
import { RouterModule, Routes } from '@angular/router'; | |||
import { BookComponent } from './book.component'; | |||
import { authGuard, permissionGuard } from '@abp/ng.core'; | |||
const routes: Routes = [{ path: '', component: BookComponent, canActivate: [authGuard, permissionGuard] }]; | |||
@NgModule({ | |||
imports: [RouterModule.forChild(routes)], | |||
exports: [RouterModule] | |||
}) | |||
export class BookRoutingModule { } |
@ -0,0 +1,122 @@ | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="row"> | |||
<div class="col col-md-6"> | |||
<h5 class="card-title"> | |||
{{ '::Menu:Books' | abpLocalization }} | |||
</h5> | |||
</div> | |||
<div class="text-end col col-md-6"> | |||
<!-- Add the "new book" button here --> | |||
<div class="text-lg-end pt-2"> | |||
<button id="create" class="btn btn-primary" type="button" (click)="createBook()"> | |||
<i class="fa fa-plus me-1"></i> | |||
<span>{{ "::NewBook" | abpLocalization }}</span> | |||
</button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<ngx-datatable [rows]="book.items" [count]="book.totalCount" [list]="list" default> | |||
<ngx-datatable-column | |||
[name]="'::Actions' | abpLocalization" | |||
[maxWidth]="150" | |||
[sortable]="false" | |||
> | |||
<ng-template let-row="row" ngx-datatable-cell-template> | |||
<div ngbDropdown container="body" class="d-inline-block"> | |||
<button | |||
class="btn btn-primary btn-sm dropdown-toggle" | |||
data-toggle="dropdown" | |||
aria-haspopup="true" | |||
ngbDropdownToggle | |||
> | |||
<i class="fa fa-cog me-1"></i>{{ '::Actions' | abpLocalization }} | |||
</button> | |||
<div ngbDropdownMenu> | |||
<button ngbDropdownItem (click)="editBook(row.id)"> | |||
{{ '::Edit' | abpLocalization }} | |||
</button> | |||
<button ngbDropdownItem (click)="delete(row.id)"> | |||
{{ '::Delete' | abpLocalization }} | |||
</button> | |||
</div> | |||
</div> | |||
</ng-template> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'::Name' | abpLocalization" prop="name"></ngx-datatable-column> | |||
<ngx-datatable-column [name]="'::Type' | abpLocalization" prop="type"> | |||
<ng-template let-row="row" ngx-datatable-cell-template> | |||
{{ '::Enum:BookType.' + row.type | abpLocalization }} | |||
</ng-template> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'::PublishDate' | abpLocalization" prop="publishDate"> | |||
<ng-template let-row="row" ngx-datatable-cell-template> | |||
{{ row.publishDate | date }} | |||
</ng-template> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'::Price' | abpLocalization" prop="price"> | |||
<ng-template let-row="row" ngx-datatable-cell-template> | |||
{{ row.price | currency }} | |||
</ng-template> | |||
</ngx-datatable-column> | |||
</ngx-datatable> | |||
</div> | |||
</div> | |||
<!-- Add the modal here --> | |||
<abp-modal [(visible)]="isModalOpen"> | |||
<ng-template #abpHeader> | |||
<h3>{{ '::NewBook' | abpLocalization }}</h3> | |||
</ng-template> | |||
<ng-template #abpBody> | |||
<form [formGroup]="form" (ngSubmit)="save()"> | |||
<div class="mt-2"> | |||
<label for="book-name">Name</label><span> * </span> | |||
<input type="text" id="book-name" class="form-control" formControlName="name" autofocus /> | |||
</div> | |||
<div class="mt-2"> | |||
<label for="book-price">Price</label><span> * </span> | |||
<input type="number" id="book-price" class="form-control" formControlName="price" /> | |||
</div> | |||
<div class="mt-2"> | |||
<label for="book-type">Type</label><span> * </span> | |||
<select class="form-control" id="book-type" formControlName="type"> | |||
<option [ngValue]="null">Select a book type</option> | |||
<option [ngValue]="type.value" *ngFor="let type of bookTypes"> {{ '::Enum:BookType.' + type.value | abpLocalization }}</option> | |||
</select> | |||
</div> | |||
<div class="mt-2"> | |||
<label>Publish date</label><span> * </span> | |||
<input | |||
#datepicker="ngbDatepicker" | |||
class="form-control" | |||
name="datepicker" | |||
formControlName="publishDate" | |||
ngbDatepicker | |||
(click)="datepicker.toggle()" | |||
/> | |||
</div> | |||
</form> | |||
</ng-template> | |||
<ng-template #abpFooter> | |||
<button type="button" class="btn btn-secondary" abpClose> | |||
{{ '::Close' | abpLocalization }} | |||
</button> | |||
<!--added save button--> | |||
<button class="btn btn-primary" (click)="save()" [disabled]="form.invalid"> | |||
<i class="fa fa-check mr-1"></i> | |||
{{ '::Save' | abpLocalization }} | |||
</button> | |||
</ng-template> | |||
</abp-modal> |
@ -0,0 +1,23 @@ | |||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
import { BookComponent } from './book.component'; | |||
describe('BookComponent', () => { | |||
let component: BookComponent; | |||
let fixture: ComponentFixture<BookComponent>; | |||
beforeEach(async () => { | |||
await TestBed.configureTestingModule({ | |||
declarations: [BookComponent] | |||
}) | |||
.compileComponents(); | |||
fixture = TestBed.createComponent(BookComponent); | |||
component = fixture.componentInstance; | |||
fixture.detectChanges(); | |||
}); | |||
it('should create', () => { | |||
expect(component).toBeTruthy(); | |||
}); | |||
}); |
@ -0,0 +1,88 @@ | |||
import { ListService, PagedResultDto } from '@abp/ng.core'; | |||
import { Component, OnInit } from '@angular/core'; | |||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | |||
import { BookService, BookDto, bookTypeOptions } from '@proxy/books'; | |||
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap'; | |||
import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared'; | |||
@Component({ | |||
selector: 'app-book', | |||
templateUrl: './book.component.html', | |||
styleUrls: ['./book.component.scss'], | |||
providers: [ListService, | |||
{ provide: NgbDateAdapter, useClass: NgbDateNativeAdapter } // add this line | |||
], | |||
}) | |||
export class BookComponent implements OnInit { | |||
book = { items: [], totalCount: 0 } as PagedResultDto<BookDto>; | |||
selectedBook = {} as BookDto; // declare selectedBook | |||
isModalOpen = false; // add this line | |||
form: FormGroup; // add this line | |||
bookTypes = bookTypeOptions; | |||
constructor(public readonly list: ListService, private bookService: BookService, private fb: FormBuilder, | |||
private confirmation: ConfirmationService | |||
) {} | |||
ngOnInit() { | |||
debugger; | |||
const bookStreamCreator = (query) => this.bookService.getList(query); | |||
this.list.hookToQuery(bookStreamCreator).subscribe((response) => { | |||
this.book = response; | |||
}); | |||
} | |||
// add new method | |||
createBook() { | |||
this.buildForm(); // add this line | |||
this.selectedBook = {} as BookDto; // reset the selected book | |||
this.isModalOpen = true; | |||
} | |||
buildForm() { | |||
this.form = this.fb.group({ | |||
name: ['', Validators.required], | |||
type: [null, Validators.required], | |||
publishDate: [null, Validators.required], | |||
price: [null, Validators.required], | |||
}); | |||
} | |||
save() { | |||
if (this.form.invalid) { | |||
return; | |||
} | |||
const request = this.selectedBook.id | |||
? this.bookService.update(this.selectedBook.id, this.form.value) | |||
: this.bookService.create(this.form.value); | |||
request.subscribe(() => { | |||
this.isModalOpen = false; | |||
this.form.reset(); | |||
this.list.get(); | |||
}); | |||
} | |||
// Add editBook method | |||
editBook(id: string) { | |||
this.bookService.get(id).subscribe((book) => { | |||
this.selectedBook = book; | |||
this.buildForm(); | |||
this.form.controls["name"].setValue(this.selectedBook.name); | |||
this.form.controls["type"].setValue(this.selectedBook.type); | |||
this.form.controls["publishDate"].setValue(this.selectedBook.publishDate); | |||
this.form.controls["price"].setValue(this.selectedBook.price); | |||
this.isModalOpen = true; | |||
}); | |||
} | |||
delete(id: string) { | |||
this.confirmation.warn('::AreYouSureToDelete', '::AreYouSure').subscribe((status) => { | |||
if (status === Confirmation.Status.confirm) { | |||
this.bookService.delete(id).subscribe(() => this.list.get()); | |||
} | |||
}); | |||
} | |||
} |
@ -0,0 +1,21 @@ | |||
import { NgModule } from '@angular/core'; | |||
import { CommonModule } from '@angular/common'; | |||
import { BookRoutingModule } from './book-routing.module'; | |||
import { BookComponent } from './book.component'; | |||
import{SharedModule} from '../shared/shared.module'; | |||
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap'; // add this line | |||
@NgModule({ | |||
declarations: [ | |||
BookComponent | |||
], | |||
imports: [ | |||
CommonModule, | |||
BookRoutingModule, | |||
SharedModule, | |||
NgbDatepickerModule | |||
] | |||
}) | |||
export class BookModule { } |
@ -0,0 +1,13 @@ | |||
import { NgModule } from '@angular/core'; | |||
import { RouterModule, Routes } from '@angular/router'; | |||
import { CustomerComponent } from './customer.component'; | |||
import { authGuard, permissionGuard } from '@abp/ng.core'; | |||
const routes: Routes = [{ path: '', component: CustomerComponent,canActivate: [authGuard, permissionGuard] }]; | |||
@NgModule({ | |||
imports: [RouterModule.forChild(routes)], | |||
exports: [RouterModule] | |||
}) | |||
export class CustomerRoutingModule { } |
@ -0,0 +1,101 @@ | |||
<div class="card"> | |||
<div class="card-header"> | |||
<div class="row"> | |||
<div class="col col-md-6"> | |||
<h5 class="card-title"> | |||
{{ 'customer' | abpLocalization }} | |||
</h5> | |||
</div> | |||
<div class="text-end col col-md-6"> | |||
<!-- Add the "new book" button here --> | |||
<div class="text-lg-end pt-2"> | |||
<button id="create" class="btn btn-primary" type="button" (click)="createCustomer()"> | |||
<i class="fa fa-plus me-1"></i> | |||
<span>{{ "New Customer" | abpLocalization }}</span> | |||
</button> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="card-body"> | |||
<ngx-datatable [rows]="customer.items" [count]="customer.totalCount" [list]="list" default> | |||
<ngx-datatable-column | |||
[name]="'::Actions' | abpLocalization" | |||
[maxWidth]="150" | |||
[sortable]="false" | |||
> | |||
<ng-template let-row="row" ngx-datatable-cell-template> | |||
<div ngbDropdown container="body" class="d-inline-block"> | |||
<button | |||
class="btn btn-primary btn-sm dropdown-toggle" | |||
data-toggle="dropdown" | |||
aria-haspopup="true" | |||
ngbDropdownToggle | |||
> | |||
<i class="fa fa-cog me-1"></i>{{ '::Actions' | abpLocalization }} | |||
</button> | |||
<div ngbDropdownMenu> | |||
<button ngbDropdownItem (click)="editCustomer(row.id)"> | |||
{{ '::Edit' | abpLocalization }} | |||
</button> | |||
<button ngbDropdownItem (click)="delete(row.id)"> | |||
{{ '::Delete' | abpLocalization }} | |||
</button> | |||
</div> | |||
</div> | |||
</ng-template> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'first Name' | abpLocalization" prop="firstName"></ngx-datatable-column> | |||
<ngx-datatable-column [name]="'Last Name' | abpLocalization" prop="lastName"> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'::Address' | abpLocalization" prop="address"> | |||
</ngx-datatable-column> | |||
<ngx-datatable-column [name]="'::Phone' | abpLocalization" prop="phone"> | |||
</ngx-datatable-column> | |||
</ngx-datatable> | |||
</div> | |||
</div> | |||
<!-- Add the modal here --> | |||
<abp-modal [(visible)]="isModalOpen"> | |||
<ng-template #abpHeader> | |||
<h3>{{ (selectedcustomer.id ? '::Edit' : '::New Customer' ) | abpLocalization }}</h3> | |||
</ng-template> | |||
<ng-template #abpBody> | |||
<form [formGroup]="form" (ngSubmit)="save()"> | |||
<div class="mt-2"> | |||
<label for="customer-first-name">First Name</label><span> * </span> | |||
<input type="text" id="customer-first-name" class="form-control" formControlName="firstName" autofocus /> | |||
</div> | |||
<div class="mt-2"> | |||
<label for="customer-last-name">Last Name</label><span> * </span> | |||
<input type="text" id="customer-last-name" class="form-control" formControlName="lastName" /> | |||
</div> | |||
<div class="mt-2"> | |||
<label for="customer-phone-name">Phone</label><span> * </span> | |||
<input type="text" id="customer-phone-name" class="form-control" formControlName="phone" /> | |||
</div> | |||
<div class="mt-2"> | |||
<label for="customer-address-name">Address</label><span> * </span> | |||
<input type="text" id="customer-address-name" class="form-control" formControlName="address" /> | |||
</div> | |||
</form> | |||
</ng-template> | |||
<ng-template #abpFooter> | |||
<button type="button" class="btn btn-secondary" abpClose> | |||
{{ '::Close' | abpLocalization }} | |||
</button> | |||
<!--added save button--> | |||
<button class="btn btn-primary" (click)="save()" [disabled]="form.invalid"> | |||
<i class="fa fa-check mr-1"></i> | |||
{{ '::Save' | abpLocalization }} | |||
</button> | |||
</ng-template> | |||
</abp-modal> |
@ -0,0 +1,23 @@ | |||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
import { CustomerComponent } from './customer.component'; | |||
describe('CustomerComponent', () => { | |||
let component: CustomerComponent; | |||
let fixture: ComponentFixture<CustomerComponent>; | |||
beforeEach(async () => { | |||
await TestBed.configureTestingModule({ | |||
declarations: [CustomerComponent] | |||
}) | |||
.compileComponents(); | |||
fixture = TestBed.createComponent(CustomerComponent); | |||
component = fixture.componentInstance; | |||
fixture.detectChanges(); | |||
}); | |||
it('should create', () => { | |||
expect(component).toBeTruthy(); | |||
}); | |||
}); |
@ -0,0 +1,92 @@ | |||
import { Component, OnInit } from '@angular/core'; | |||
import { ListService, PagedResultDto } from '@abp/ng.core'; | |||
import { CustomerDto, CustomerService } from '@proxy/customers'; | |||
import { FormGroup, FormBuilder, Validators } from '@angular/forms'; | |||
import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared'; | |||
@Component({ | |||
selector: 'app-customer', | |||
templateUrl: './customer.component.html', | |||
styleUrl: './customer.component.scss', | |||
providers: [ListService] | |||
}) | |||
export class CustomerComponent implements OnInit { | |||
customer = { items: [], totalCount: 0 } as PagedResultDto<CustomerDto>; | |||
isModalOpen = false; | |||
form: FormGroup; | |||
selectedcustomer = {} as CustomerDto; | |||
constructor(public readonly list: ListService, | |||
private customerService: CustomerService, | |||
private fb: FormBuilder, | |||
private confirmation: ConfirmationService ) {} | |||
ngOnInit() { | |||
debugger; | |||
const bookStreamCreator = (query) => this.customerService.getList(query); | |||
this.list.hookToQuery(bookStreamCreator).subscribe((response) => { | |||
this.customer = response; | |||
}); | |||
} | |||
// add new method | |||
createCustomer() { | |||
this.selectedcustomer = {} as CustomerDto; | |||
this.buildForm(); | |||
this.isModalOpen = true; | |||
} | |||
editCustomer(id: number) { | |||
this.customerService.get(id).subscribe((customer) => { | |||
debugger; | |||
this.selectedcustomer = customer; | |||
this.buildForm(); | |||
this.isModalOpen = true; | |||
}); | |||
} | |||
buildForm() { | |||
this.form = this.fb.group({ | |||
firstName: [this.selectedcustomer.firstName || '', Validators.required], | |||
lastName: [this.selectedcustomer.lastName, Validators.required], | |||
phone: [this.selectedcustomer.phone, Validators.required], | |||
address: [this.selectedcustomer.address, Validators.required], | |||
}); | |||
} | |||
// add save method | |||
save() { | |||
if (this.form.invalid) { | |||
return; | |||
} | |||
debugger; | |||
const request = this.selectedcustomer.id | |||
? this.customerService.update(this.selectedcustomer.id, this.form.value) | |||
: this.customerService.create(this.form.value); | |||
if(this.selectedcustomer.id){ | |||
this.customerService.update(this.selectedcustomer.id,this.form.value).subscribe(() => { | |||
this.isModalOpen = false; | |||
this.form.reset(); | |||
this.list.get(); | |||
}); | |||
} | |||
else{ | |||
this.customerService.create(this.form.value).subscribe(() => { | |||
this.isModalOpen = false; | |||
this.form.reset(); | |||
this.list.get(); | |||
}); | |||
} | |||
} | |||
delete(id: number) { | |||
this.confirmation.warn('::AreYouSureToDelete', '::AreYouSure').subscribe((status) => { | |||
if (status === Confirmation.Status.confirm) { | |||
this.customerService.delete(id).subscribe(() => this.list.get()); | |||
} | |||
}); | |||
} | |||
} |
@ -0,0 +1,20 @@ | |||
import { NgModule } from '@angular/core'; | |||
import { CommonModule } from '@angular/common'; | |||
import { CustomerRoutingModule } from './customer-routing.module'; | |||
import { CustomerComponent } from './customer.component'; | |||
import{SharedModule} from '../shared/shared.module'; | |||
@NgModule({ | |||
declarations: [ | |||
CustomerComponent | |||
], | |||
imports: [ | |||
CommonModule, | |||
CustomerRoutingModule, | |||
SharedModule | |||
] | |||
}) | |||
export class CustomerModule { } |
@ -0,0 +1,17 @@ | |||
# Proxy Generation Output | |||
This directory includes the output of the latest proxy generation. | |||
The files and folders in it will be overwritten when proxy generation is run again. | |||
Therefore, please do not place your own content in this folder. | |||
In addition, `generate-proxy.json` works like a lock file. | |||
It includes information used by the proxy generator, so please do not delete or modify it. | |||
Finally, the name of the files and folders should not be changed for two reasons: | |||
- Proxy generator will keep creating them at those paths and you will have multiple copies of the same content. | |||
- ABP Suite generates files which include imports from this folder. | |||
> **Important Notice:** If you are building a module and are planning to publish to npm, | |||
> some of the generated proxies are likely to be exported from public-api.ts file. In such a case, | |||
> please make sure you export files directly and not from barrel exports. In other words, | |||
> do not include index.ts exports in your public-api.ts exports. |
@ -0,0 +1,56 @@ | |||
import type { AuthorDto, CreateAuthorDto, GetAuthorListDto, UpdateAuthorDto } from './models'; | |||
import { RestService, Rest } from '@abp/ng.core'; | |||
import type { PagedResultDto } from '@abp/ng.core'; | |||
import { Injectable } from '@angular/core'; | |||
@Injectable({ | |||
providedIn: 'root', | |||
}) | |||
export class AuthorService { | |||
apiName = 'Default'; | |||
create = (input: CreateAuthorDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, AuthorDto>({ | |||
method: 'POST', | |||
url: '/api/app/author', | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
delete = (id: string, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, void>({ | |||
method: 'DELETE', | |||
url: `/api/app/author/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
get = (id: string, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, AuthorDto>({ | |||
method: 'GET', | |||
url: `/api/app/author/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
getList = (input: GetAuthorListDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, PagedResultDto<AuthorDto>>({ | |||
method: 'GET', | |||
url: '/api/app/author', | |||
params: { filter: input.filter, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount }, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
update = (id: string, input: UpdateAuthorDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, void>({ | |||
method: 'PUT', | |||
url: `/api/app/author/${id}`, | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
constructor(private restService: RestService) {} | |||
} |
@ -0,0 +1,2 @@ | |||
export * from './author.service'; | |||
export * from './models'; |
@ -0,0 +1,23 @@ | |||
import type { EntityDto, PagedAndSortedResultRequestDto } from '@abp/ng.core'; | |||
export interface AuthorDto extends EntityDto<string> { | |||
name?: string; | |||
birthDate?: string; | |||
shortBio?: string; | |||
} | |||
export interface CreateAuthorDto { | |||
name: string; | |||
birthDate: string; | |||
shortBio?: string; | |||
} | |||
export interface GetAuthorListDto extends PagedAndSortedResultRequestDto { | |||
filter?: string; | |||
} | |||
export interface UpdateAuthorDto { | |||
name: string; | |||
birthDate: string; | |||
shortBio?: string; | |||
} |
@ -0,0 +1,55 @@ | |||
import type { BookIssueDto, BookIssueListDto } from './models'; | |||
import { RestService, Rest } from '@abp/ng.core'; | |||
import type { PagedResultDto } from '@abp/ng.core'; | |||
import { Injectable } from '@angular/core'; | |||
@Injectable({ | |||
providedIn: 'root', | |||
}) | |||
export class BookIssueService { | |||
apiName = 'Default'; | |||
create = (input: BookIssueDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, BookIssueDto>({ | |||
method: 'POST', | |||
url: '/api/app/book-issue', | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
delete = (id: number, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, void>({ | |||
method: 'DELETE', | |||
url: `/api/app/book-issue/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
get = (id: number, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, BookIssueDto>({ | |||
method: 'GET', | |||
url: `/api/app/book-issue/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
getList = (config?: Partial<Rest.Config>) => | |||
this.restService.request<any, PagedResultDto<BookIssueListDto>>({ | |||
method: 'GET', | |||
url: '/api/app/book-issue', | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
update = (id: number, input: BookIssueDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, void>({ | |||
method: 'PUT', | |||
url: `/api/app/book-issue/${id}`, | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
constructor(private restService: RestService) {} | |||
} |
@ -0,0 +1,2 @@ | |||
export * from './book-issue.service'; | |||
export * from './models'; |
@ -0,0 +1,13 @@ | |||
import type { EntityDto } from '@abp/ng.core'; | |||
export interface BookIssueDto extends EntityDto<number> { | |||
bookId?: string; | |||
customerId: number; | |||
} | |||
export interface BookIssueListDto { | |||
bookIssueId: number; | |||
bookName?: string; | |||
customerName?: string; | |||
issueDate?: string; | |||
} |
@ -0,0 +1,15 @@ | |||
import { mapEnumToOptions } from '@abp/ng.core'; | |||
export enum BookType { | |||
Undefined = 0, | |||
Adventure = 1, | |||
Biography = 2, | |||
Dystopia = 3, | |||
Fantastic = 4, | |||
Horror = 5, | |||
Science = 6, | |||
ScienceFiction = 7, | |||
Poetry = 8, | |||
} | |||
export const bookTypeOptions = mapEnumToOptions(BookType); |
@ -0,0 +1,64 @@ | |||
import type { BookDto, CreateUpdateBookDto } from './models'; | |||
import { RestService, Rest } from '@abp/ng.core'; | |||
import type { PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core'; | |||
import { Injectable } from '@angular/core'; | |||
@Injectable({ | |||
providedIn: 'root', | |||
}) | |||
export class BookService { | |||
apiName = 'Default'; | |||
create = (input: CreateUpdateBookDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, BookDto>({ | |||
method: 'POST', | |||
url: '/api/app/book', | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
delete = (id: string, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, void>({ | |||
method: 'DELETE', | |||
url: `/api/app/book/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
get = (id: string, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, BookDto>({ | |||
method: 'GET', | |||
url: `/api/app/book/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
getBookDropDown = (config?: Partial<Rest.Config>) => | |||
this.restService.request<any, BookDto[]>({ | |||
method: 'GET', | |||
url: '/api/app/book/book-drop-down', | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
getList = (input: PagedAndSortedResultRequestDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, PagedResultDto<BookDto>>({ | |||
method: 'GET', | |||
url: '/api/app/book', | |||
params: { sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount }, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
update = (id: string, input: CreateUpdateBookDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, BookDto>({ | |||
method: 'PUT', | |||
url: `/api/app/book/${id}`, | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
constructor(private restService: RestService) {} | |||
} |
@ -0,0 +1,3 @@ | |||
export * from './book-type.enum'; | |||
export * from './book.service'; | |||
export * from './models'; |
@ -0,0 +1,16 @@ | |||
import type { AuditedEntityDto } from '@abp/ng.core'; | |||
import type { BookType } from './book-type.enum'; | |||
export interface BookDto extends AuditedEntityDto<string> { | |||
name?: string; | |||
type: BookType; | |||
publishDate?: string; | |||
price: number; | |||
} | |||
export interface CreateUpdateBookDto { | |||
name: string; | |||
type: BookType; | |||
publishDate: string; | |||
price: number; | |||
} |
@ -0,0 +1,63 @@ | |||
import type { CustomerDto } from './models'; | |||
import { RestService, Rest } from '@abp/ng.core'; | |||
import type { PagedResultDto } from '@abp/ng.core'; | |||
import { Injectable } from '@angular/core'; | |||
@Injectable({ | |||
providedIn: 'root', | |||
}) | |||
export class CustomerService { | |||
apiName = 'Default'; | |||
create = (input: CustomerDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, CustomerDto>({ | |||
method: 'POST', | |||
url: '/api/app/customer', | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
delete = (id: number, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, void>({ | |||
method: 'DELETE', | |||
url: `/api/app/customer/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
get = (id: number, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, CustomerDto>({ | |||
method: 'GET', | |||
url: `/api/app/customer/${id}`, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
getList = (config?: Partial<Rest.Config>) => | |||
this.restService.request<any, PagedResultDto<CustomerDto>>({ | |||
method: 'GET', | |||
url: '/api/app/customer', | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
getcustomerDropDown = (config?: Partial<Rest.Config>) => | |||
this.restService.request<any, CustomerDto[]>({ | |||
method: 'GET', | |||
url: '/api/app/customer/customer-drop-down', | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
update = (id: number, input: CustomerDto, config?: Partial<Rest.Config>) => | |||
this.restService.request<any, void>({ | |||
method: 'PUT', | |||
url: `/api/app/customer/${id}`, | |||
body: input, | |||
}, | |||
{ apiName: this.apiName,...config }); | |||
constructor(private restService: RestService) {} | |||
} |
@ -0,0 +1,2 @@ | |||
export * from './customer.service'; | |||
export * from './models'; |
@ -0,0 +1,8 @@ | |||
import type { EntityDto } from '@abp/ng.core'; | |||
export interface CustomerDto extends EntityDto<number> { | |||
firstName?: string; | |||
lastName?: string; | |||
phone?: string; | |||
address?: string; | |||
} |
@ -0,0 +1,5 @@ | |||
import * as Authors from './authors'; | |||
import * as BookIssued from './book-issued'; | |||
import * as Books from './books'; | |||
import * as Customers from './customers'; | |||
export { Authors, BookIssued, Books, Customers }; |
@ -1,19 +1,16 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="utf-8"/> | |||
<meta charset="utf-8" /> | |||
<title>BookStore</title> | |||
<base href="/"/> | |||
<base href="/" /> | |||
<meta name="viewport" content="width=device-width, initial-scale=1"/> | |||
<link rel="icon" type="image/x-icon" href="favicon.ico"/> | |||
<link rel="manifest" href="manifest.webmanifest"> | |||
<meta name="theme-color" content="#1976d2"> | |||
</head> | |||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | |||
<link rel="icon" type="image/x-icon" href="favicon.ico" /> | |||
</head> | |||
<body class="bg-light"> | |||
<app-root> | |||
<div class="donut centered"></div> | |||
</app-root> | |||
<noscript>Please enable JavaScript to continue using this application.</noscript> | |||
</body> | |||
</body> | |||
</html> |
@ -0,0 +1,44 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Text; | |||
using Volo.Abp.Application.Dtos; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
public class AuthorDto : EntityDto<Guid> | |||
{ | |||
public string Name { get; set; } | |||
public DateTime BirthDate { get; set; } | |||
public string ShortBio { get; set; } | |||
} | |||
public class GetAuthorListDto : PagedAndSortedResultRequestDto | |||
{ | |||
public string? Filter { get; set; } | |||
} | |||
public class CreateAuthorDto | |||
{ | |||
[Required] | |||
[StringLength(AuthorConsts.MaxNameLength)] | |||
public string Name { get; set; } = string.Empty; | |||
[Required] | |||
public DateTime BirthDate { get; set; } | |||
public string? ShortBio { get; set; } | |||
} | |||
public class UpdateAuthorDto | |||
{ | |||
[Required] | |||
[StringLength(AuthorConsts.MaxNameLength)] | |||
public string Name { get; set; } = string.Empty; | |||
[Required] | |||
public DateTime BirthDate { get; set; } | |||
public string? ShortBio { get; set; } | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Application.Dtos; | |||
using Volo.Abp.Application.Services; | |||
namespace Acme.BookStore.Authors; | |||
public interface IAuthorAppService : IApplicationService | |||
{ | |||
Task<AuthorDto> GetAsync(Guid id); | |||
Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input); | |||
Task<AuthorDto> CreateAsync(CreateAuthorDto input); | |||
Task UpdateAsync(Guid id, UpdateAuthorDto input); | |||
Task DeleteAsync(Guid id); | |||
} |
@ -0,0 +1,25 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Text; | |||
using Volo.Abp.Application.Dtos; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public class BookIssueDto : EntityDto<int> | |||
{ | |||
[Required] | |||
public Guid bookId { get; set; } | |||
[Required] | |||
public int customerId { get; set; } | |||
} | |||
public class BookIssueListDto | |||
{ | |||
public int bookIssueId { get; set; } | |||
public string bookName { get; set; } | |||
public string customerName { get; set; } | |||
public DateTime issueDate { get; set; } | |||
} | |||
} |
@ -0,0 +1,22 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Application.Dtos; | |||
using Volo.Abp.Application.Services; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public interface IBookIssueAppService : IApplicationService | |||
{ | |||
Task<BookIssueDto> GetAsync(int id); | |||
Task<PagedResultDto<BookIssueListDto>> GetListAsync(); | |||
Task<BookIssueDto> CreateAsync(BookIssueDto input); | |||
Task UpdateAsync(int id, BookIssueDto input); | |||
Task DeleteAsync(int id); | |||
} | |||
} |
@ -0,0 +1,18 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using Volo.Abp.Application.Dtos; | |||
namespace Acme.BookStore.Books | |||
{ | |||
public class BookDto : AuditedEntityDto<Guid> | |||
{ | |||
public string Name { get; set; } | |||
public BookType Type { get; set; } | |||
public DateTime PublishDate { get; set; } | |||
public float Price { get; set; } | |||
} | |||
} |
@ -0,0 +1,24 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Text; | |||
namespace Acme.BookStore.Books | |||
{ | |||
public class CreateUpdateBookDto | |||
{ | |||
[Required] | |||
[StringLength(128)] | |||
public string Name { get; set; } = string.Empty; | |||
[Required] | |||
public BookType Type { get; set; } = BookType.Undefined; | |||
[Required] | |||
[DataType(DataType.Date)] | |||
public DateTime PublishDate { get; set; } = DateTime.Now; | |||
[Required] | |||
public float Price { get; set; } | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Application.Dtos; | |||
using Volo.Abp.Application.Services; | |||
namespace Acme.BookStore.Books | |||
{ | |||
public interface IBookAppService : | |||
ICrudAppService< //Defines CRUD methods | |||
BookDto, //Used to show books | |||
Guid, //Primary key of the book entity | |||
PagedAndSortedResultRequestDto, //Used for paging/sorting | |||
CreateUpdateBookDto> //Used to create/update a book | |||
{ | |||
Task<List<BookDto>> GetBookDropDown(); | |||
} | |||
} |
@ -0,0 +1,20 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Text; | |||
using Volo.Abp.Application.Dtos; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public class CustomerDto : EntityDto<int> | |||
{ | |||
[Required] | |||
public string firstName { get; set; } | |||
[Required] | |||
public string lastName { get; set; } | |||
[Required] | |||
public string phone { get; set; } | |||
[Required] | |||
public string address { get; set; } | |||
} | |||
} |
@ -0,0 +1,24 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Application.Dtos; | |||
using Volo.Abp.Application.Services; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public interface ICustomerAppService : IApplicationService | |||
{ | |||
Task<CustomerDto> GetAsync(int id); | |||
Task<PagedResultDto<CustomerDto>> GetListAsync(); | |||
Task<CustomerDto> CreateAsync(CustomerDto input); | |||
Task UpdateAsync(int id, CustomerDto input); | |||
Task DeleteAsync(int id); | |||
Task<List<CustomerDto>> GetcustomerDropDown(); | |||
} | |||
} |
@ -0,0 +1,95 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Acme.BookStore.Permissions; | |||
using Microsoft.AspNetCore.Authorization; | |||
using Volo.Abp.Application.Dtos; | |||
using Volo.Abp.Domain.Repositories; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
[Authorize(BookStorePermissions.Authors.Default)] | |||
public class AuthorAppService : BookStoreAppService, IAuthorAppService | |||
{ | |||
private readonly IAuthorRepository _authorRepository; | |||
private readonly AuthorManager _authorManager; | |||
public AuthorAppService( | |||
IAuthorRepository authorRepository, | |||
AuthorManager authorManager) | |||
{ | |||
_authorRepository = authorRepository; | |||
_authorManager = authorManager; | |||
} | |||
public async Task<AuthorDto> GetAsync(Guid id) | |||
{ | |||
var author = await _authorRepository.GetAsync(id); | |||
return ObjectMapper.Map<Author, AuthorDto>(author); | |||
} | |||
public async Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input) | |||
{ | |||
if (input.Sorting.IsNullOrWhiteSpace()) | |||
{ | |||
input.Sorting = nameof(Author.Name); | |||
} | |||
var authors = await _authorRepository.GetListAsync( | |||
input.SkipCount, | |||
input.MaxResultCount, | |||
input.Sorting, | |||
input.Filter | |||
); | |||
var totalCount = input.Filter == null | |||
? await _authorRepository.CountAsync() | |||
: await _authorRepository.CountAsync( | |||
author => author.Name.Contains(input.Filter)); | |||
return new PagedResultDto<AuthorDto>( | |||
totalCount, | |||
ObjectMapper.Map<List<Author>, List<AuthorDto>>(authors) | |||
); | |||
} | |||
[Authorize(BookStorePermissions.Authors.Create)] | |||
public async Task<AuthorDto> CreateAsync(CreateAuthorDto input) | |||
{ | |||
var author = await _authorManager.CreateAsync( | |||
input.Name, | |||
input.BirthDate, | |||
input.ShortBio | |||
); | |||
await _authorRepository.InsertAsync(author); | |||
return ObjectMapper.Map<Author, AuthorDto>(author); | |||
} | |||
[Authorize(BookStorePermissions.Authors.Edit)] | |||
public async Task UpdateAsync(Guid id, UpdateAuthorDto input) | |||
{ | |||
var author = await _authorRepository.GetAsync(id); | |||
if (author.Name != input.Name) | |||
{ | |||
await _authorManager.ChangeNameAsync(author, input.Name); | |||
} | |||
author.BirthDate = input.BirthDate; | |||
author.ShortBio = input.ShortBio; | |||
await _authorRepository.UpdateAsync(author); | |||
} | |||
[Authorize(BookStorePermissions.Authors.Delete)] | |||
public async Task DeleteAsync(Guid id) | |||
{ | |||
await _authorRepository.DeleteAsync(id); | |||
} | |||
} | |||
} |
@ -0,0 +1,73 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Acme.BookStore.BookIssued; | |||
using Volo.Abp.Application.Dtos; | |||
using Acme.BookStore.Permissions; | |||
using Microsoft.AspNetCore.Authorization; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public class BookIssueAppService : BookStoreAppService, IBookIssueAppService | |||
{ | |||
private readonly IBookIssueRepository _bookIssueRepository; | |||
private readonly BookIssueManager _bookIssueManager; | |||
public BookIssueAppService( | |||
IBookIssueRepository bookIssueRepository, | |||
BookIssueManager bookIssueManager) | |||
{ | |||
_bookIssueRepository = bookIssueRepository; | |||
_bookIssueManager = bookIssueManager; | |||
} | |||
public async Task<BookIssueDto> GetAsync(int id) | |||
{ | |||
var cus = await _bookIssueRepository.GetAsync(id); | |||
return ObjectMapper.Map<BookIssue, BookIssueDto>(cus); | |||
} | |||
public async Task<PagedResultDto<BookIssueListDto>> GetListAsync() | |||
{ | |||
var cus = await _bookIssueRepository.BookIssueList(); | |||
return new PagedResultDto<BookIssueListDto>( | |||
cus.Count(), | |||
ObjectMapper.Map<List<BookIssueList>, List<BookIssueListDto>>(cus) | |||
); | |||
} | |||
[Authorize(BookStorePermissions.BookIssued.Create)] | |||
public async Task<BookIssueDto> CreateAsync(BookIssueDto input) | |||
{ | |||
var cus = ObjectMapper.Map<BookIssueDto, BookIssue>(input); | |||
var cust = await _bookIssueManager.CreateAsync(cus); | |||
var res = await _bookIssueRepository.InsertAsync(cust); | |||
return ObjectMapper.Map<BookIssue, BookIssueDto>(cust); | |||
} | |||
[Authorize(BookStorePermissions.BookIssued.Edit)] | |||
public async Task UpdateAsync(int id, BookIssueDto input) | |||
{ | |||
var cus = await _bookIssueRepository.GetAsync(id); | |||
await _bookIssueRepository.UpdateAsync(cus); | |||
} | |||
[Authorize(BookStorePermissions.BookIssued.Delete)] | |||
public async Task DeleteAsync(int id) | |||
{ | |||
await _bookIssueRepository.DeleteAsync(id); | |||
} | |||
} | |||
} |
@ -0,0 +1,43 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Application.Dtos; | |||
using Volo.Abp.Application.Services; | |||
using Volo.Abp.Domain.Repositories; | |||
using Acme.BookStore.Permissions; | |||
namespace Acme.BookStore.Books | |||
{ | |||
public class BookAppService : | |||
CrudAppService< | |||
Book, //The Book entity | |||
BookDto, //Used to show books | |||
Guid, //Primary key of the book entity | |||
PagedAndSortedResultRequestDto, //Used for paging/sorting | |||
CreateUpdateBookDto>, //Used to create/update a book | |||
IBookAppService //implement the IBookAppService | |||
{ | |||
private readonly IRepository<Book, Guid> _bookRepository; | |||
public BookAppService(IRepository<Book, Guid> repository) | |||
: base(repository) | |||
{ | |||
_bookRepository = repository; | |||
GetPolicyName = BookStorePermissions.Books.Default; | |||
GetListPolicyName = BookStorePermissions.Books.Default; | |||
CreatePolicyName = BookStorePermissions.Books.Create; | |||
UpdatePolicyName = BookStorePermissions.Books.Edit; | |||
DeletePolicyName = BookStorePermissions.Books.Delete; | |||
} | |||
public async Task<List<BookDto>> GetBookDropDown() | |||
{ | |||
var cus = await _bookRepository.GetListAsync(); | |||
cus = cus == null ? new List<Book>() : cus; | |||
return ObjectMapper.Map<List<Book>, List<BookDto>>(cus); | |||
} | |||
} | |||
} |
@ -0,0 +1,86 @@ | |||
using Acme.BookStore.Customers; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Application.Dtos; | |||
using Volo.Abp.Application.Services; | |||
using Volo.Abp.ObjectMapping; | |||
using Acme.BookStore.Permissions; | |||
using Microsoft.AspNetCore.Authorization; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public class CustomerAppService: BookStoreAppService, ICustomerAppService | |||
{ | |||
private readonly ICustomerRepository _customerRepository; | |||
private readonly CustomerManager _customerManager; | |||
public CustomerAppService( | |||
ICustomerRepository customerRepository, | |||
CustomerManager customerManager) | |||
{ | |||
_customerRepository = customerRepository; | |||
_customerManager = customerManager; | |||
} | |||
public async Task<CustomerDto> GetAsync(int id) | |||
{ | |||
var cus = await _customerRepository.GetAsync(id); | |||
return ObjectMapper.Map<Customer, CustomerDto>(cus); | |||
} | |||
public async Task<List<CustomerDto>> GetcustomerDropDown() | |||
{ | |||
var cus = await _customerRepository.GetListAsync(); | |||
cus = cus == null ? new List<Customer>() : cus; | |||
return ObjectMapper.Map<List<Customer>, List<CustomerDto>>(cus); | |||
} | |||
public async Task<PagedResultDto<CustomerDto>> GetListAsync() | |||
{ | |||
var cus = await _customerRepository.GetListAsync(); | |||
return new PagedResultDto<CustomerDto>( | |||
cus.Count(), | |||
ObjectMapper.Map<List<Customer>, List<CustomerDto>>(cus) | |||
); | |||
} | |||
[Authorize(BookStorePermissions.Customers.Create)] | |||
public async Task<CustomerDto> CreateAsync(CustomerDto input) | |||
{ | |||
var cus = ObjectMapper.Map<CustomerDto,Customer>(input); | |||
var cust = await _customerManager.CreateAsync(cus); | |||
await _customerRepository.InsertAsync(cust); | |||
return ObjectMapper.Map<Customer, CustomerDto>(cust); | |||
} | |||
[Authorize(BookStorePermissions.Customers.Edit)] | |||
public async Task UpdateAsync(int id, CustomerDto input) | |||
{ | |||
var cus = await _customerRepository.GetAsync(id); | |||
if (cus.phone == input.phone) | |||
{ | |||
await _customerManager.ChangeNameAsync(cus, input.firstName,input.lastName); | |||
} | |||
await _customerRepository.UpdateAsync(cus); | |||
} | |||
[Authorize(BookStorePermissions.Customers.Delete)] | |||
public async Task DeleteAsync(int id) | |||
{ | |||
await _customerRepository.DeleteAsync(id); | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
public static class AuthorConsts | |||
{ | |||
public const int MaxNameLength = 64; | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace Acme.BookStore.Books | |||
{ | |||
public enum BookType | |||
{ | |||
Undefined, | |||
Adventure, | |||
Biography, | |||
Dystopia, | |||
Fantastic, | |||
Horror, | |||
Science, | |||
ScienceFiction, | |||
Poetry | |||
} | |||
} |
@ -0,0 +1,13 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public class CustomerConsts | |||
{ | |||
public const int MaxNameLength = 100; | |||
public const int MaxPhoneLength = 14; | |||
} | |||
} |
@ -0,0 +1,48 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
using Volo.Abp.Domain.Entities.Auditing; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
public class Author : FullAuditedAggregateRoot<Guid> | |||
{ | |||
public string Name { get; private set; } | |||
public DateTime BirthDate { get; set; } | |||
public string ShortBio { get; set; } | |||
private Author() | |||
{ | |||
/* This constructor is for deserialization / ORM purpose */ | |||
} | |||
internal Author( | |||
Guid id, | |||
string name, | |||
DateTime birthDate, | |||
string? shortBio = null) | |||
: base(id) | |||
{ | |||
SetName(name); | |||
BirthDate = birthDate; | |||
ShortBio = shortBio; | |||
} | |||
internal Author ChangeName(string name) | |||
{ | |||
SetName(name); | |||
return this; | |||
} | |||
private void SetName(string name) | |||
{ | |||
Name = Check.NotNullOrWhiteSpace( | |||
name, | |||
nameof(name), | |||
maxLength: AuthorConsts.MaxNameLength | |||
); | |||
} | |||
} | |||
} |
@ -0,0 +1,18 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
public class AuthorAlreadyExistsException : BusinessException | |||
{ | |||
public AuthorAlreadyExistsException(string name) | |||
: base(BookStoreDomainErrorCodes.AuthorAlreadyExists) | |||
{ | |||
WithData("name", name); | |||
} | |||
} | |||
} |
@ -0,0 +1,57 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
using Volo.Abp.Domain.Services; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
public class AuthorManager : DomainService | |||
{ | |||
private readonly IAuthorRepository _authorRepository; | |||
public AuthorManager(IAuthorRepository authorRepository) | |||
{ | |||
_authorRepository = authorRepository; | |||
} | |||
public async Task<Author> CreateAsync( | |||
string name, | |||
DateTime birthDate, | |||
string? shortBio = null) | |||
{ | |||
Check.NotNullOrWhiteSpace(name, nameof(name)); | |||
var existingAuthor = await _authorRepository.FindByNameAsync(name); | |||
if (existingAuthor != null) | |||
{ | |||
throw new AuthorAlreadyExistsException(name); | |||
} | |||
return new Author( | |||
GuidGenerator.Create(), | |||
name, | |||
birthDate, | |||
shortBio | |||
); | |||
} | |||
public async Task ChangeNameAsync( | |||
Author author, | |||
string newName) | |||
{ | |||
Check.NotNull(author, nameof(author)); | |||
Check.NotNullOrWhiteSpace(newName, nameof(newName)); | |||
var existingAuthor = await _authorRepository.FindByNameAsync(newName); | |||
if (existingAuthor != null && existingAuthor.Id != author.Id) | |||
{ | |||
throw new AuthorAlreadyExistsException(newName); | |||
} | |||
author.ChangeName(newName); | |||
} | |||
} | |||
} |
@ -0,0 +1,21 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Domain.Repositories; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
public interface IAuthorRepository : IRepository<Author, Guid> | |||
{ | |||
Task<Author> FindByNameAsync(string name); | |||
Task<List<Author>> GetListAsync( | |||
int skipCount, | |||
int maxResultCount, | |||
string sorting, | |||
string filter = null | |||
); | |||
} | |||
} |
@ -0,0 +1,33 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Domain.Entities.Auditing; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public class BookIssue : FullAuditedAggregateRoot<int> | |||
{ | |||
public Guid bookId { get; set; } | |||
public int customerId { get; set; } | |||
private BookIssue() | |||
{ | |||
/* This constructor is for deserialization / ORM purpose */ | |||
} | |||
internal BookIssue(int id, Guid bookId, int customerId) : base(id) | |||
{ | |||
this.bookId = bookId; | |||
this.customerId = customerId; | |||
} | |||
} | |||
public class BookIssueList | |||
{ | |||
public int bookIssueId { get; set; } | |||
public string bookName { get; set; } | |||
public string customerName { get; set; } | |||
public DateTime issueDate { get; set; } | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public class BookIssueErrorException : BusinessException | |||
{ | |||
public BookIssueErrorException(string customerName, string bookName) | |||
: base(BookStoreDomainErrorCodes.BookIssuedAlready) | |||
{ | |||
WithData("customer", customerName); | |||
WithData("book", bookName); | |||
} | |||
} | |||
} |
@ -0,0 +1,36 @@ | |||
using Acme.BookStore.Customers; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
using Volo.Abp.Domain.Services; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public class BookIssueManager : DomainService | |||
{ | |||
private readonly IBookIssueRepository _bookIssueRepository; | |||
public BookIssueManager(IBookIssueRepository bookIssueRepository) | |||
{ | |||
_bookIssueRepository = bookIssueRepository; | |||
} | |||
public async Task<BookIssue> CreateAsync( | |||
BookIssue bookissue) | |||
{ | |||
var existingBookIssue = await _bookIssueRepository.FindBookIssueCustomer(bookissue.customerId,bookissue.bookId); | |||
if (existingBookIssue != null) | |||
{ | |||
throw new BookIssueErrorException(existingBookIssue.customerName, existingBookIssue.bookName); | |||
} | |||
return new BookIssue( | |||
await _bookIssueRepository.NewBookIssueId(), | |||
bookissue.bookId, | |||
bookissue.customerId | |||
); | |||
} | |||
} | |||
} |
@ -0,0 +1,17 @@ | |||
using Acme.BookStore.Customers; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Domain.Repositories; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public interface IBookIssueRepository : IRepository<BookIssue, int> | |||
{ | |||
Task<BookIssueList> FindBookIssueCustomer(int customerId, Guid bookId); | |||
Task<int> NewBookIssueId(); | |||
Task<List<BookIssueList>> BookIssueList(); | |||
} | |||
} |
@ -0,0 +1,100 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Acme.BookStore.Books; | |||
using Volo.Abp.Data; | |||
using Volo.Abp.DependencyInjection; | |||
using Volo.Abp.Domain.Repositories; | |||
using Acme.BookStore.Authors; | |||
using Acme.BookStore.Customers; | |||
namespace Acme.BookStore | |||
{ | |||
public class BookStoreDataSeederContributor | |||
: IDataSeedContributor, ITransientDependency | |||
{ | |||
private readonly IRepository<Book, Guid> _bookRepository; | |||
private readonly IAuthorRepository _authorRepository; | |||
private readonly ICustomerRepository _customerRepository; | |||
private readonly AuthorManager _authorManager; | |||
private readonly CustomerManager _customerManager; | |||
public BookStoreDataSeederContributor(IRepository<Book, Guid> bookRepository, | |||
IAuthorRepository authorRepository, | |||
AuthorManager authorManager, | |||
ICustomerRepository customerRepository, | |||
CustomerManager customerManager | |||
) | |||
{ | |||
_bookRepository = bookRepository; | |||
_authorRepository = authorRepository; | |||
_authorManager = authorManager; | |||
_customerRepository = customerRepository; | |||
_customerManager = customerManager; | |||
} | |||
public async Task SeedAsync(DataSeedContext context) | |||
{ | |||
if (await _bookRepository.GetCountAsync() <= 0) | |||
{ | |||
await _bookRepository.InsertAsync( | |||
new Book | |||
{ | |||
Name = "1984", | |||
Type = BookType.Dystopia, | |||
PublishDate = new DateTime(1949, 6, 8), | |||
Price = 19.84f | |||
}, | |||
autoSave: true | |||
); | |||
await _bookRepository.InsertAsync( | |||
new Book | |||
{ | |||
Name = "The Hitchhiker's Guide to the Galaxy", | |||
Type = BookType.ScienceFiction, | |||
PublishDate = new DateTime(1995, 9, 27), | |||
Price = 42.0f | |||
}, | |||
autoSave: true | |||
); | |||
} | |||
if (await _authorRepository.GetCountAsync() <= 0) | |||
{ | |||
await _authorRepository.InsertAsync( | |||
await _authorManager.CreateAsync( | |||
"George Orwell", | |||
new DateTime(1903, 06, 25), | |||
"Orwell produced literary criticism and poetry, fiction and polemical journalism; and is best known for the allegorical novella Animal Farm (1945) and the dystopian novel Nineteen Eighty-Four (1949)." | |||
) | |||
); | |||
await _authorRepository.InsertAsync( | |||
await _authorManager.CreateAsync( | |||
"Douglas Adams", | |||
new DateTime(1952, 03, 11), | |||
"Douglas Adams was an English author, screenwriter, essayist, humorist, satirist and dramatist. Adams was an advocate for environmentalism and conservation, a lover of fast cars, technological innovation and the Apple Macintosh, and a self-proclaimed 'radical atheist'." | |||
) | |||
); | |||
} | |||
if (await _customerRepository.GetCountAsync() <= 0) | |||
{ | |||
Customer customer = new Customer(1, "soumen", "pal", "9091184026", "haripal"); | |||
await _customerRepository.InsertAsync( | |||
await _customerManager.CreateAsync(customer) | |||
); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,20 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Domain.Entities.Auditing; | |||
namespace Acme.BookStore.Books | |||
{ | |||
public class Book : AuditedAggregateRoot<Guid> | |||
{ | |||
public string Name { get; set; } | |||
public BookType Type { get; set; } | |||
public DateTime PublishDate { get; set; } | |||
public float Price { get; set; } | |||
} | |||
} |
@ -0,0 +1,60 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
using Volo.Abp.Domain.Entities.Auditing; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public class Customer : FullAuditedAggregateRoot<int> | |||
{ | |||
public string firstName { get; set; } | |||
public string lastName { get; set; } | |||
public string phone { get; set; } | |||
public string address { get; set; } | |||
private Customer() | |||
{ | |||
/* This constructor is for deserialization / ORM purpose */ | |||
} | |||
internal Customer(int id, string firstName, string lastName, string phone, string address) : base(id) | |||
{ | |||
this.firstName = firstName; | |||
this.lastName = lastName; | |||
this.phone = phone; | |||
this.address = address; | |||
} | |||
internal Customer ChangeFirstName(string firstname) | |||
{ | |||
SetFirstName(firstname); | |||
return this; | |||
} | |||
private void SetFirstName(string firstName) | |||
{ | |||
firstName = Check.NotNullOrWhiteSpace( | |||
firstName, | |||
nameof(firstName), | |||
maxLength: CustomerConsts.MaxNameLength | |||
); | |||
this.firstName = firstName; | |||
} | |||
internal Customer ChangeLastName(string lastname) | |||
{ | |||
SetLastName(lastname); | |||
return this; | |||
} | |||
private void SetLastName(string lastname) | |||
{ | |||
lastname = Check.NotNullOrWhiteSpace( | |||
lastname, | |||
nameof(lastname), | |||
maxLength: CustomerConsts.MaxNameLength | |||
); | |||
this.lastName = lastname; | |||
} | |||
} | |||
} |
@ -0,0 +1,18 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public class CustomerErrorException : BusinessException | |||
{ | |||
public CustomerErrorException(string phone) | |||
: base(BookStoreDomainErrorCodes.CustomerPhoneAlreadyExists) | |||
{ | |||
WithData("phone", phone); | |||
} | |||
} | |||
} |
@ -0,0 +1,55 @@ | |||
using Acme.BookStore.Authors; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Guids; | |||
using Volo.Abp; | |||
using Volo.Abp.Domain.Services; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public class CustomerManager : DomainService | |||
{ | |||
private readonly ICustomerRepository _customerRepository; | |||
public CustomerManager(ICustomerRepository customerRepository) | |||
{ | |||
_customerRepository = customerRepository; | |||
} | |||
public async Task<Customer> CreateAsync( | |||
Customer customer) | |||
{ | |||
Check.NotNullOrWhiteSpace(customer.firstName, nameof(customer.firstName)); | |||
Check.NotNullOrWhiteSpace(customer.lastName, nameof(customer.lastName)); | |||
var existingAuthor = await _customerRepository.FindByPhoneAsync(customer.phone); | |||
if (existingAuthor != null) | |||
{ | |||
throw new CustomerErrorException(customer.phone); | |||
} | |||
return new Customer( | |||
await _customerRepository.NewCustomerId(), | |||
customer.firstName, | |||
customer.lastName, | |||
customer.phone, | |||
customer.address | |||
); | |||
} | |||
public async Task ChangeNameAsync( | |||
Customer customer, | |||
string firstName,string lastName) | |||
{ | |||
Check.NotNull(customer, nameof(customer)); | |||
Check.NotNullOrWhiteSpace(customer.firstName, nameof(customer.firstName)); | |||
Check.NotNullOrWhiteSpace(customer.lastName, nameof(customer.lastName)); | |||
customer.ChangeFirstName(firstName); | |||
customer.ChangeLastName(lastName); | |||
} | |||
} | |||
} |
@ -0,0 +1,16 @@ | |||
using Acme.BookStore.Authors; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Domain.Repositories; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public interface ICustomerRepository : IRepository<Customer, int> | |||
{ | |||
Task<Customer> FindByPhoneAsync(string phone); | |||
Task<int> NewCustomerId(); | |||
} | |||
} |
@ -0,0 +1,56 @@ | |||
using Acme.BookStore.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; | |||
using Volo.Abp.EntityFrameworkCore; | |||
namespace Acme.BookStore.Authors | |||
{ | |||
public class EfCoreAuthorRepository | |||
: EfCoreRepository<BookStoreDbContext, Author, Guid>, | |||
IAuthorRepository | |||
{ | |||
public EfCoreAuthorRepository( | |||
IDbContextProvider<BookStoreDbContext> dbContextProvider) | |||
: base(dbContextProvider) | |||
{ | |||
} | |||
public async Task<Author> FindByNameAsync(string name) | |||
{ | |||
var dbSet = await GetDbSetAsync(); | |||
return await dbSet.FirstOrDefaultAsync(author => author.Name == name); | |||
} | |||
public async Task<List<Author>> GetListAsync( | |||
int skipCount, | |||
int maxResultCount, | |||
string sorting, | |||
string filter = null) | |||
{ | |||
var dbSet = await GetDbSetAsync(); | |||
return await dbSet.WhereIf( | |||
!filter.IsNullOrEmpty(), | |||
author=>author.Name.Contains(filter)).OrderBy(author=> author.Name).Skip(skipCount).Take(maxResultCount).ToListAsync(); | |||
//return await dbSet | |||
// .WhereIf( | |||
// !filter.IsNullOrWhiteSpace(), | |||
// author => author.Name.Contains(filter) | |||
// ) | |||
// .OrderBy(sorting) | |||
// .Skip(skipCount) | |||
// .Take(maxResultCount) | |||
// .ToListAsync(); | |||
} | |||
} | |||
} |
@ -0,0 +1,85 @@ | |||
using Acme.BookStore.Customers; | |||
using Acme.BookStore.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore; | |||
using Polly; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp; | |||
using Volo.Abp.Data; | |||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; | |||
using Volo.Abp.EntityFrameworkCore; | |||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory; | |||
namespace Acme.BookStore.BookIssued | |||
{ | |||
public class EfCoreBookIssueRepository : EfCoreRepository<BookStoreDbContext, BookIssue, int>, | |||
IBookIssueRepository | |||
{ | |||
private readonly IDataFilter _dataFilter; | |||
public EfCoreBookIssueRepository( | |||
IDbContextProvider<BookStoreDbContext> dbContextProvider, IDataFilter dataFilter | |||
) | |||
: base(dbContextProvider) | |||
{ | |||
_dataFilter = dataFilter; | |||
} | |||
public async Task<BookIssueList> FindBookIssueCustomer(int customerId, Guid bookId) | |||
{ | |||
//var dbSet = await GetDbSetAsync(); | |||
var dbContext = await GetDbContextAsync(); | |||
List<BookIssueList> item = ( | |||
from bi in dbContext.bookIssues | |||
join cu in dbContext.Customers on bi.customerId equals cu.Id | |||
join bk in dbContext.Books on bi.bookId equals bk.Id | |||
where (bi.customerId == customerId && bi.bookId == bookId && bi.IsDeleted == false) | |||
select new BookIssueList | |||
{ | |||
bookIssueId = bi.Id, | |||
bookName = bk.Name, | |||
customerName = cu.firstName + " " + cu.lastName, | |||
issueDate = bi.CreationTime | |||
}).ToList(); | |||
return item == null? null : item.FirstOrDefault(); | |||
} | |||
public async Task<int> NewBookIssueId() | |||
{ | |||
using (_dataFilter.Disable<ISoftDelete>()) | |||
{ | |||
var dbSet = await GetDbSetAsync(); | |||
var values = await dbSet.MaxAsync(u => (int?)u.Id); | |||
return values == null ? 0 + 1 : (int)values + 1; | |||
} | |||
} | |||
public async Task<List<BookIssueList>> BookIssueList() | |||
{ | |||
var dbContext = await GetDbContextAsync(); | |||
List<BookIssueList> item = ( | |||
from bi in dbContext.bookIssues | |||
join cu in dbContext.Customers on bi.customerId equals cu.Id | |||
join bk in dbContext.Books on bi.bookId equals bk.Id | |||
select new BookIssueList | |||
{ | |||
bookIssueId = bi.Id, | |||
bookName = bk.Name, | |||
customerName = cu.firstName + " " + cu.lastName, | |||
issueDate = bi.CreationTime | |||
}).ToList(); | |||
return item; | |||
} | |||
} | |||
} |
@ -0,0 +1,40 @@ | |||
using Acme.BookStore.Authors; | |||
using Acme.BookStore.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; | |||
using Volo.Abp.EntityFrameworkCore; | |||
namespace Acme.BookStore.Customers | |||
{ | |||
public class EfCoreCustomerRepository : EfCoreRepository<BookStoreDbContext, Customer, int>, | |||
ICustomerRepository | |||
{ | |||
public EfCoreCustomerRepository( | |||
IDbContextProvider<BookStoreDbContext> dbContextProvider) | |||
: base(dbContextProvider) | |||
{ | |||
} | |||
public async Task<Customer> FindByPhoneAsync(string phone) | |||
{ | |||
var dbSet = await GetDbSetAsync(); | |||
return await dbSet.FirstOrDefaultAsync(cust => cust.phone == phone); | |||
} | |||
public async Task<int> NewCustomerId() | |||
{ | |||
var dbSet = await GetDbSetAsync(); | |||
var values = await dbSet.MaxAsync(u => (int?)u.Id); | |||
return values == null ? 0 +1: (int)values + 1; | |||
} | |||
} | |||
} |
@ -0,0 +1,43 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
#nullable disable | |||
namespace Acme.BookStore.Migrations | |||
{ | |||
/// <inheritdoc /> | |||
public partial class Created_Book_Entity : Migration | |||
{ | |||
/// <inheritdoc /> | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.CreateTable( | |||
name: "AppBooks", | |||
columns: table => new | |||
{ | |||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), | |||
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false), | |||
Type = table.Column<int>(type: "int", nullable: false), | |||
PublishDate = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
Price = table.Column<float>(type: "real", nullable: false), | |||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false), | |||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_AppBooks", x => x.Id); | |||
}); | |||
} | |||
/// <inheritdoc /> | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.DropTable( | |||
name: "AppBooks"); | |||
} | |||
} | |||
} |
@ -0,0 +1,50 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
#nullable disable | |||
namespace Acme.BookStore.Migrations | |||
{ | |||
/// <inheritdoc /> | |||
public partial class Added_Authors : Migration | |||
{ | |||
/// <inheritdoc /> | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.CreateTable( | |||
name: "AppAuthors", | |||
columns: table => new | |||
{ | |||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false), | |||
Name = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false), | |||
BirthDate = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
ShortBio = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false), | |||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), | |||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_AppAuthors", x => x.Id); | |||
}); | |||
migrationBuilder.CreateIndex( | |||
name: "IX_AppAuthors_Name", | |||
table: "AppAuthors", | |||
column: "Name"); | |||
} | |||
/// <inheritdoc /> | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.DropTable( | |||
name: "AppAuthors"); | |||
} | |||
} | |||
} |
@ -0,0 +1,47 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
#nullable disable | |||
namespace Acme.BookStore.Migrations | |||
{ | |||
/// <inheritdoc /> | |||
public partial class Added_Customers : Migration | |||
{ | |||
/// <inheritdoc /> | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.CreateTable( | |||
name: "AppCustomers", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(type: "int", nullable: false) | |||
.Annotation("SqlServer:Identity", "1, 1"), | |||
firstName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), | |||
lastName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false), | |||
phone = table.Column<string>(type: "nvarchar(14)", maxLength: 14, nullable: false), | |||
address = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false), | |||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), | |||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_AppCustomers", x => x.Id); | |||
}); | |||
} | |||
/// <inheritdoc /> | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.DropTable( | |||
name: "AppCustomers"); | |||
} | |||
} | |||
} |
@ -0,0 +1,50 @@ | |||
using System; | |||
using Microsoft.EntityFrameworkCore.Migrations; | |||
#nullable disable | |||
namespace Acme.BookStore.Migrations | |||
{ | |||
/// <inheritdoc /> | |||
public partial class Added_BookIssued : Migration | |||
{ | |||
/// <inheritdoc /> | |||
protected override void Up(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.EnsureSchema( | |||
name: "BKN"); | |||
migrationBuilder.CreateTable( | |||
name: "AppBookIssued", | |||
schema: "BKN", | |||
columns: table => new | |||
{ | |||
Id = table.Column<int>(type: "int", nullable: false) | |||
.Annotation("SqlServer:Identity", "1, 1"), | |||
bookId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), | |||
customerId = table.Column<int>(type: "int", nullable: false), | |||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false), | |||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false), | |||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), | |||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true), | |||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), | |||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true), | |||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true) | |||
}, | |||
constraints: table => | |||
{ | |||
table.PrimaryKey("PK_AppBookIssued", x => x.Id); | |||
}); | |||
} | |||
/// <inheritdoc /> | |||
protected override void Down(MigrationBuilder migrationBuilder) | |||
{ | |||
migrationBuilder.DropTable( | |||
name: "AppBookIssued", | |||
schema: "BKN"); | |||
} | |||
} | |||
} |