Skip to content

Commit

Permalink
feat(reporter): copy directly into bl-admin (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
AdrianAndersen authored Jun 25, 2024
1 parent 3e2e876 commit 51bf3b3
Show file tree
Hide file tree
Showing 44 changed files with 2,617 additions and 41 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"@angular/router": "^11.2.4",
"@boklisten/bl-connect": "^0.20.6",
"@boklisten/bl-login": "^1.2.20",
"@boklisten/bl-reporter": "^0.4.13",
"@fortawesome/angular-fontawesome": "^0.8.2",
"@fortawesome/fontawesome-svg-core": "^1.2.34",
"@fortawesome/free-brands-svg-icons": "^5.15.2",
Expand Down
115 changes: 115 additions & 0 deletions src/app/database/database-reports/reporter/excel/excel.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { Injectable } from "@angular/core";
import { read, write, utils, WorkBook, writeFile } from "xlsx";
import moment from "moment-es6";

@Injectable({
providedIn: "root",
})
export class ExcelService {
constructor() {}

public objectsToExcelFile(objects: any[], fileName: string) {
const flattenObjects = [];

for (const obj of objects) {
flattenObjects.push(this.flattenObj(obj));
}

const sheet = utils.json_to_sheet(flattenObjects);
const workBook: WorkBook = utils.book_new();
const fileNameWithDate = this.generateFileName(fileName);
utils.book_append_sheet(workBook, sheet, fileNameWithDate);

writeFile(workBook, fileNameWithDate);
}

public excelFileToObjects(excelBinaryFile: any): any[] {
const workbook = read(excelBinaryFile, { type: "array" });
const jsonWorkbook = utils.sheet_to_json(
workbook.Sheets[workbook.SheetNames[0]],
{ raw: true }
);
const objectArray = [];

for (const obj of jsonWorkbook) {
objectArray.push(this.flattenObjToRegular(obj));
}

return objectArray;
}

private generateFileName(name: string): string {
const time = moment().format("DDMMYYYYHHmm");
return name + "_" + time + ".xlsx";
}

private flattenObjToRegular(flattenObj: any) {
const regularObj = {};

for (const objKey in flattenObj) {
if (!flattenObj.hasOwnProperty(objKey)) {
continue;
}

const splittedKey = objKey.toString().split(".");

this.addFlattenObjToRegular(
regularObj,
splittedKey,
flattenObj[objKey]
);
}

return regularObj;
}

private addFlattenObjToRegular(parentObj: any, keys: string[], value: any) {
const currentKey = keys[0];

if (keys.length <= 1) {
if (value === "false") {
parentObj[keys[0]] = false;
} else if (value === "true") {
parentObj[keys[0]] = true;
} else {
parentObj[keys[0]] = value;
}

return;
}

if (!parentObj.hasOwnProperty(currentKey)) {
parentObj[currentKey] = {};
}

keys.shift(); // removes the current key from array
return this.addFlattenObjToRegular(parentObj[currentKey], keys, value);
}

private flattenObj(obj: any): any {
const toReturn = {};
let flatObject = {};

for (const objKey in obj) {
if (!obj.hasOwnProperty(objKey)) {
continue;
}

if (typeof obj[objKey] === "object") {
flatObject = this.flattenObj(obj[objKey]);

for (const i in flatObject) {
if (!flatObject.hasOwnProperty(i)) {
continue;
}

toReturn[objKey + (!!isNaN(i as any) ? "." + i : "")] =
flatObject[i];
}
} else {
toReturn[objKey] = obj[objKey];
}
}
return toReturn;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h6 i18n="@@customerItemDownloadTitle">Customer Items</h6>
</div>
<div class="card-body">
<div class="row mb-2" *ngIf="wait">
<div class="col-12">
<app-bl-common-update-button [wait]="wait">
</app-bl-common-update-button>
</div>
</div>

<div
class="row justify-content-between"
*ngIf="currentBranchId"
>
<div class="col-auto">
<fa-icon [icon]="'location-arrow'"></fa-icon>
</div>
<div class="col-auto">
<app-bl-common-toggle-button
[(value)]="currentBranch"
></app-bl-common-toggle-button>
</div>
</div>

<div class="row justify-content-between">
<div class="col-auto" i18n="@@customerItemDownloadReturned">
Returned
</div>
<div class="col-auto">
<app-bl-common-toggle-button
[(value)]="returned"
></app-bl-common-toggle-button>
</div>
</div>

<div class="row justify-content-between">
<div
class="col-auto"
i18n="@@customerItemDownloadNotReturned"
>
Not returned
</div>
<div class="col-auto">
<app-bl-common-toggle-button
[(value)]="notReturned"
></app-bl-common-toggle-button>
</div>
</div>

<div class="row justify-content-between">
<div class="col-auto" i18n="@@customerItemDownloadBuyout">
Buyout
</div>
<div class="col-auto">
<app-bl-common-toggle-button
[(value)]="buyout"
></app-bl-common-toggle-button>
</div>
</div>

<div class="row mt-2 justify-content-center">
<div class="col-auto">
<app-blc-period-select
(periodChange)="onPeriodChange($event)"
>
</app-blc-period-select>
</div>
</div>

<div class="row mt-5">
<div class="col-12">
<button
type="button"
class="btn btn-outline-info btn-block"
(click)="onPrintCustomerItems()"
>
<span class="mr-2"
><fa-icon [icon]="'file-excel'"></fa-icon
></span>
<span i18n="@@[reportPrintCustomerItemsButton]"
>Print customer items</span
>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing";
import {
Component,
Input,
Output,
EventEmitter,
Injectable,
} from "@angular/core";

import { CustomerItemDownloadComponent } from "./customer-item-download.component";
import { CustomerItemDownloadService } from "./customer-item-download.service";

@Component({ selector: "app-bl-common-update-button", template: "" })
class BlCommonUpdateButtonStubComponent {
@Input() wait;
}

@Component({ selector: "app-bl-common-toggle-button", template: "" })
class BlCommonToggleButtonStubComponent {
@Input() value;
@Output() valueChange;

constructor() {
this.valueChange = new EventEmitter<any>();
}
}

@Component({ selector: "fa-icon", template: "" })
class FaIconStub {
@Input() icon;
}

@Component({ selector: "app-blc-period-select", template: "" })
class BlcPeriodSelectStubComponent {
@Output() periodChange;

constructor() {
this.periodChange = new EventEmitter<any>();
}
}

@Injectable()
class CustomerItemDownloadStubService {}

describe("CustomerItemDownloadComponent", () => {
let component: CustomerItemDownloadComponent;
let fixture: ComponentFixture<CustomerItemDownloadComponent>;
let customerItemDownloadServiceSpy;

beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [
CustomerItemDownloadComponent,
BlCommonUpdateButtonStubComponent,
BlCommonToggleButtonStubComponent,
BlcPeriodSelectStubComponent,
FaIconStub,
],
providers: [
{
provide: CustomerItemDownloadService,
useClass: CustomerItemDownloadStubService,
},
],
}).compileComponents();
})
);

beforeEach(() => {
fixture = TestBed.createComponent(CustomerItemDownloadComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it("should create", () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Component, OnInit, Input } from "@angular/core";
import { CustomerItemDownloadService } from "./customer-item-download.service";
import { CustomerItemFilter } from "./customerItemFilter";
import { CustomerItem } from "@boklisten/bl-model";

@Component({
selector: "app-customer-item-download",
templateUrl: "./customer-item-download.component.html",
styleUrls: ["./customer-item-download.component.scss"],
})
export class CustomerItemDownloadComponent implements OnInit {
@Input() currentBranchId: string;
public currentBranch: boolean;
public customerItemFilter: CustomerItemFilter;
public wait: boolean;
public returned: boolean;
public notReturned: boolean;
public noCustomerItemsFound: boolean;
public buyout: boolean;

constructor(
private customerItemDownloadService: CustomerItemDownloadService
) {
this.wait = false;
this.noCustomerItemsFound = false;
this.returned = false;
this.notReturned = true;
this.buyout = false;

this.customerItemFilter = {
fromDate: new Date(),
toDate: new Date(),
};
}

ngOnInit() {
this.currentBranch = typeof this.currentBranchId !== "undefined";
}

public onPeriodChange(period: { fromDate: Date; toDate: Date }) {
this.customerItemFilter.fromDate = period.fromDate;
this.customerItemFilter.toDate = period.toDate;
}

public onPrintCustomerItems() {
if (this.currentBranch && typeof this.currentBranchId !== "undefined") {
this.customerItemFilter["branchIds"] = [this.currentBranchId];
}

if (!this.returned && this.notReturned) {
this.customerItemFilter["returned"] = false;
} else if (this.returned && !this.notReturned) {
this.customerItemFilter["returned"] = true;
} else {
this.customerItemFilter["returned"] = undefined;
}

this.customerItemFilter["buyout"] = this.buyout;

this.wait = true;
this.noCustomerItemsFound = false;

this.customerItemDownloadService
.getCustomerItemsByFilter(this.customerItemFilter)
.then((filteredCustomerItems: CustomerItem[]) => {
this.customerItemDownloadService.printCustomerItemsToExcelFile(
filteredCustomerItems,
"customerItems"
);
this.wait = false;
})
.catch((err) => {
this.wait = false;
this.noCustomerItemsFound = true;
});
}
}
Loading

0 comments on commit 51bf3b3

Please sign in to comment.