Информация по транзакциям
This commit is contained in:
gofnnp 2023-05-10 02:38:17 +04:00
parent 42b46bc478
commit 76f1799b22
5 changed files with 470 additions and 300 deletions

View File

@ -1,4 +1,4 @@
import {OrderStatus, Page, PageCode} from "./interface/data"; import {OrderStatus, Page, PageCode, lvlPeriod} from "./interface/data";
export const PageList: Page[] = [ export const PageList: Page[] = [
{ {
@ -65,3 +65,29 @@ export const orderStatuses: OrderStatus = {
'Delivered': 'Выполнен', 'Delivered': 'Выполнен',
'Closed': 'Выполнен', 'Closed': 'Выполнен',
}; };
export const lvlPeriods: lvlPeriod[] = [
{
percent: 3,
start: 0,
end: 1600,
color: '#f2c94c'
},
{
percent: 6,
start: 1601,
end: 3600,
color: '#f2994a'
},
{
percent: 10,
start: 3601,
end: 8600,
color: '#6fcf97'
},
{
percent: 15,
start: 8601,
color: '#6fcf97'
},
]

View File

@ -1,11 +1,9 @@
export enum PageCode { export enum PageCode {
Auth, Auth,
Orders, Orders,
BonusProgram, BonusProgram,
RefSystem, RefSystem,
UserData UserData,
} }
export interface Page { export interface Page {
@ -15,7 +13,7 @@ export interface Page {
description?: string; description?: string;
getMethod?: string; getMethod?: string;
resName?: string; resName?: string;
onSideBar: boolean onSideBar: boolean;
} }
export interface UserDataForm { export interface UserDataForm {
@ -42,12 +40,16 @@ export interface Purchase {
PurchaseDate: string; PurchaseDate: string;
PurchaseState?: number; PurchaseState?: number;
CardNumber?: number; CardNumber?: number;
Address?: string Address?: string;
CheckSummary?: number CheckSummary?: number;
BonusSummary?: number BonusSummary?: number;
ID: string; ID: string;
Transactions: Transaction[]; Transactions: Transaction[];
IsSingleTransaction?: boolean; IsSingleTransaction?: boolean;
transactionCreateDate?: string;
transactionType?: 'CancelPayFromWallet' | 'PayFromWallet' | 'RefillWallet';
transactionSum: number;
orderSum?: number;
} }
export interface Transaction { export interface Transaction {
@ -69,6 +71,13 @@ export interface OrderStatus{
[key: string]: string; [key: string]: string;
} }
export interface lvlPeriod {
percent: number;
start: number;
end?: number;
color: string;
}
export interface DeliveryType { export interface DeliveryType {
cost: number; cost: number;
title: string; title: string;
@ -92,7 +101,7 @@ export interface AcceptedOrder {
total: number; total: number;
}; };
date_created: string; date_created: string;
items: OrderProduct[] items: OrderProduct[];
} }
export interface Product { export interface Product {
@ -136,8 +145,8 @@ export interface OrderProduct{
name: string; name: string;
price: number; price: number;
modifiers: { modifiers: {
[name: string]: OrderModifier[] [name: string]: OrderModifier[];
} };
} }
export interface OrderModifier { export interface OrderModifier {

View File

@ -1,33 +1,33 @@
<app-navbar title="Карта гостя" (backEvent)="logout()"></app-navbar> <app-navbar title="Карта гостя" (backEvent)="logout()"></app-navbar>
<ng-container
*ngTemplateOutlet="appTpl; context: { user: customerInfo | async }"
></ng-container>
<ng-template #appTpl let-user="user">
<div class="guest-card"> <div class="guest-card">
<div class="guest-card__qr" (click)="qrCodeClick()"> <div class="guest-card__qr" (click)="qrCodeClick()">
<ng-container *ngIf="customerInfo">
<qr-code <qr-code
*ngIf="user; else spinner" [value]="customerInfo?.phone.substr(2) || 'Данные не найдены'"
[value]="user?.customer_info?.phone.substr(2) || 'Данные не найдены'"
[margin]="0" [margin]="0"
[size]="qrCodeSize" [size]="qrCodeSize"
errorCorrectionLevel="M" errorCorrectionLevel="M"
></qr-code> ></qr-code>
</ng-container>
<ng-container *ngIf="!customerInfo">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 85 }"
></ng-container>
</ng-container>
</div> </div>
<div class="guest-card__user-description"> <div class="guest-card__user-description">
Текущий баланс бонусов: Текущий баланс бонусов:
<span *ngIf="user"> <span *ngIf="customerInfo">
{{ {{ getBalanceAmount(customerInfo?.walletBalances) }}
getBalanceAmount(user?.customer_info?.walletBalances)
}}
бонусов</span бонусов</span
> >
</div> </div>
<span id="bonuses-condition"></span>
<app-accordion header="Условия начисления бонусов"> <app-accordion header="Условия начисления бонусов">
<p> <p>
Расчет начисления бонусов - 10% от суммы покупок за период с Расчет начисления бонусов - 10% от суммы покупок за период с 11.01.2023г.
11.01.2023г. по 31.03.2023 г. по 31.03.2023 г.
</p> </p>
<p> <p>
За период с 11.01.2023г. по 31.03.2023 г. сумма ваших покупок составила За период с 11.01.2023г. по 31.03.2023 г. сумма ваших покупок составила
@ -42,14 +42,14 @@
</p> </p>
<p> <p>
Списание Бонусов происходит из расчета 1:1 (один Бонус дает скидку 1 Списание Бонусов происходит из расчета 1:1 (один Бонус дает скидку 1
российский рубль / 1 тенге / 1 белорусский рубль. Скидка, российский рубль / 1 тенге / 1 белорусский рубль. Скидка, предоставляемая
предоставляемая Участнику при списании Бонусов, уменьшает цену товаров в Участнику при списании Бонусов, уменьшает цену товаров в заказе в
заказе в соответствии с условиями ПЛ. соответствии с условиями ПЛ.
</p> </p>
<p> <p>
Для списания Бонусов Участник должен попросить об этом в кофе-баре сети Для списания Бонусов Участник должен попросить об этом в кофе-баре сети
«COFFEE LIKE» кассира до момента пробития фискального чека, после чего «COFFEE LIKE» кассира до момента пробития фискального чека, после чего им
им будет проверена возможность списания Бонусов. будет проверена возможность списания Бонусов.
</p> </p>
<p> <p>
Для всех Участников возможно списание без использования мобильного Для всех Участников возможно списание без использования мобильного
@ -79,8 +79,8 @@
Возврат покупки, которая была оплачена бонусами: Возврат покупки, которая была оплачена бонусами:
<li> <li>
В случае предъявления Участником кассового или товарного чека, сумма В случае предъявления Участником кассового или товарного чека, сумма
бонусов, списанная для оплаты возвращаемого товара, зачисляется на бонусов, списанная для оплаты возвращаемого товара, зачисляется на счет
счет участника. участника.
</li> </li>
<li> <li>
В случае возврата товара с применением оплаты бонусами, клиенту В случае возврата товара с применением оплаты бонусами, клиенту
@ -90,8 +90,22 @@
</ul> </ul>
</app-accordion> </app-accordion>
<div class="guest-card__purchases-description"> <div
Сумма ваших покупок за период с 01.04.2023г. - <span>1200 руб.</span> class="guest-card__purchases-description"
[ngStyle]="{
display: purchaseData.$loading ? 'grid' : 'block'
}"
>
Сумма ваших покупок за период с
{{ purchaseData.currentPeriod[0].format("DD.MM.yyyyг.") }} -
<span *ngIf="!purchaseData.$loading"
>{{ purchaseData.currentAmount }} руб.</span
>
<ng-container *ngIf="purchaseData.$loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 24 }"
></ng-container>
</ng-container>
</div> </div>
<app-accordion header="Узнать % начисляемых бонусов"> <app-accordion header="Узнать % начисляемых бонусов">
<p> <p>
@ -99,51 +113,74 @@
зависимости от уровня: зависимости от уровня:
</p> </p>
<ng-container
*ngFor="let item of lvlPeriods; let index = index; let last = last"
>
<ng-container *ngIf="!last">
<ul> <ul>
<span style="color: #f2c94c">Уровень 1</span> <span [style]="{ color: item.color }">Уровень {{ index + 1 }}</span>
<li>Сумма покупок за предыдущий период 0-1600 руб.</li> <li>
<li>Начисляемый бонус 3% от суммы покупки</li> Сумма покупок за предыдущий период {{ item.start }}-{{ item.end }}
руб.
</li>
<li>Начисляемый бонус {{ item.percent }}% от суммы покупки</li>
</ul> </ul>
<br /> <br />
</ng-container>
<ng-container *ngIf="last">
<ul> <ul>
<span style="color: #f2994a">Уровень 2</span> <span [style]="{ color: item.color }">Уровень {{ index + 1 }}</span>
<li>Сумма покупок за предыдущий период 1601-3600 руб.</li> <li>Сумма покупок за предыдущий период — от {{ item.start }} руб.</li>
<li>Начисляемый бонус 6% от суммы покупки</li> <li>Начисляемый бонус, в % от суммы покупки - {{ item.percent }}%</li>
</ul>
<br />
<ul>
<span style="color: #6fcf97">Уровень 3</span>
<li>Сумма покупок за предыдущий период  3601-8600 руб.</li>
<li>Начисляемый бонус 10% от суммы покупки</li>
</ul>
<br />
<ul>
<span style="color: #6fcf97">Уровень 4</span>
<li>Сумма покупок за предыдущий период — от 8601 руб.</li>
<li>Начисляемый бонус, в % от суммы покупки - 15%</li>
</ul> </ul>
</ng-container>
</ng-container>
</app-accordion> </app-accordion>
<div class="guest-card__level-info"> <div class="guest-card__level-info">
<ng-container *ngIf="!purchaseData.$loading">
<ng-container *ngIf="currentLvlPeriod.end">
<h2> <h2>
До следующего уровня за период с 01.04.2023 по 30.06.2023г осталось До следующего уровня за период с
совершить покупки на 401 рублей {{ purchaseData.currentPeriod[0].format("DD.MM.yyyyг") }} по
{{ purchaseData.currentPeriod[1].format("DD.MM.yyyyг") }}
осталось совершить покупки на {{ currentLvlPeriod.end - (purchaseData.currentAmount || 0) + 1 }} рублей
</h2> </h2>
<input <input
type="range" type="range"
[(ngModel)]="discountLevel" [value]="purchaseData.currentAmount"
[min]="3" [min]="currentLvlPeriod.start"
[max]="6" [max]="currentLvlPeriod.end"
[step]="0.1" [step]="0.01"
disabled="true"
[ngStyle]="{ [ngStyle]="{
'background-size': ((discountLevel - 3) / (6 - 3)) * 100 + '% 100%' 'background-size': ((purchaseData.currentAmount! - currentLvlPeriod.start) / (currentLvlPeriod.end - currentLvlPeriod.start + 1)) * 100 + '% 100%'
}" }"
/> />
</ng-container>
<ng-container *ngIf="!currentLvlPeriod.end">
<h2>
У Вас последний уровень бонусной программы. Процент начисляемых бонусов: {{currentLvlPeriod.percent}}%
</h2>
</ng-container>
</ng-container>
<ng-container *ngIf="purchaseData.$loading">
<ng-container
*ngTemplateOutlet="spinner; context: { $implicit: 48 }"
></ng-container>
</ng-container>
<p class="show-more">Узнать условия начисления бонусов</p> <p class="show-more">
<a href="#bonuses-condition">
Узнать условия начисления бонусов
</a>
</p>
</div> </div>
<hr /> <hr />
<app-last-order></app-last-order> <app-last-order
[lastOrder]="lastPurchase"
[loading]="purchaseData.$loading"
></app-last-order>
<hr /> <hr />
<app-invite-friends></app-invite-friends> <app-invite-friends></app-invite-friends>
<hr /> <hr />
@ -155,8 +192,7 @@
Программы лояльности</a Программы лояльности</a
> >
</div> </div>
</ng-template>
<ng-template #spinner> <ng-template #spinner let-diameter>
<mat-spinner></mat-spinner> <mat-spinner [strokeWidth]="3" [diameter]="diameter"></mat-spinner>
</ng-template> </ng-template>

View File

@ -62,6 +62,7 @@
font-size: 16px; font-size: 16px;
line-height: 19px; line-height: 19px;
letter-spacing: -0.5px; letter-spacing: -0.5px;
grid-template-columns: calc(100% - 24px) 24px;
span { span {
color: #219653; color: #219653;
@ -70,6 +71,9 @@
&__level-info { &__level-info {
padding: 36px; padding: 36px;
display: flex;
flex-direction: column;
align-items: center;
h2 { h2 {
font-style: normal; font-style: normal;
@ -152,9 +156,12 @@
font-size: 12px; font-size: 12px;
line-height: 16px; line-height: 16px;
text-align: center; text-align: center;
a {
text-decoration: none;
color: #28af49; color: #28af49;
} }
} }
}
&__download-app { &__download-app {
width: 100%; width: 100%;

View File

@ -7,9 +7,21 @@ import { CookiesService } from 'src/app/services/cookies.service';
import { WpJsonService } from 'src/app/services/wp-json.service'; import { WpJsonService } from 'src/app/services/wp-json.service';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import moment from 'moment'; import moment from 'moment';
import { Purchase, lvlPeriod } from 'src/app/interface/data';
import { lvlPeriods } from 'src/app/app.constants';
interface Moment extends moment.Moment {} interface Moment extends moment.Moment {}
export interface IPurchaseData {
currentPeriod: Moment[];
lastPeriod: Moment[];
lastPurchases: Purchase[];
currentPurchases: Purchase[];
lastAmount?: number;
currentAmount?: number;
$loading: boolean;
}
@Component({ @Component({
selector: 'app-guest-card', selector: 'app-guest-card',
templateUrl: './guest-card.component.html', templateUrl: './guest-card.component.html',
@ -18,10 +30,35 @@ interface Moment extends moment.Moment {}
export class GuestCardComponent implements OnInit { export class GuestCardComponent implements OnInit {
public qrCodeSize: number = 85; public qrCodeSize: number = 85;
private isQrCodeClicked: boolean = false; private isQrCodeClicked: boolean = false;
public customerInfo!: Observable<any>; public customerInfo!: any;
public purchases!: Observable<any>; public purchases!: Purchase[];
public lastPurchase!: Purchase;
public purchaseData: IPurchaseData = {
currentPeriod: [],
lastPeriod: [],
lastPurchases: [],
currentPurchases: [],
$loading: true,
get currentAmount():number {
// const amount = this.currentPurchases.reduce((accumulator, currentValue) => {
// if (currentValue.transactionType !== 'PayFromWallet') return 0;
// return accumulator + currentValue.transactionSum;
// }, 0);
// return amount * -1
return 8601
},
get lastAmount():number {
const amount = this.lastPurchases.reduce((accumulator, currentValue) => {
if (currentValue.transactionType !== 'PayFromWallet') return 0;
return accumulator + currentValue.transactionSum;
}, 0);
return amount * -1
}
};
public discountLevel: number = 4.2; public discountLevel: number = 4.2;
public lvlPeriods: lvlPeriod[] = lvlPeriods;
public currentLvlPeriod!: lvlPeriod;
constructor( constructor(
private _bottomSheet: MatBottomSheet, private _bottomSheet: MatBottomSheet,
@ -32,13 +69,44 @@ export class GuestCardComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
const token = this.cookiesService.getItem('token'); const token = this.cookiesService.getItem('token');
this.customerInfo = this.wpJsonService.getCustomerInfo( this.getCurrentQuarterOfYear();
this.wpJsonService
.getCustomerInfo(
environment.systemId, environment.systemId,
token || '', token || '',
environment.icardProxy environment.icardProxy
)
.subscribe({
next: (value) => {
this.customerInfo = value.customer_info;
this.getPurchases().subscribe((value) => {
this.purchases = value[this.customerInfo?.id].filter(
(purchase: Purchase) =>
[
'PayFromWallet',
'CancelPayFromWallet',
'RefillWallet',
].includes(purchase.transactionType || '')
); );
this.purchases = this.getPurchases(); this.lastPurchase = value[this.customerInfo?.id].filter(
this.purchases.subscribe((value) => console.log(value)); (purchase: Purchase) =>
[
'PayFromWallet',
].includes(purchase.transactionType || '')
)[0]
this.purchaseData.lastPurchases = this.purchases.filter((value: Purchase) => {
return moment(value.transactionCreateDate).isBetween(this.purchaseData.lastPeriod[0], this.purchaseData.lastPeriod[1])
})
this.purchaseData.currentPurchases = this.purchases.filter((value: Purchase) => {
return moment(value.transactionCreateDate).isBetween(this.purchaseData.currentPeriod[0], this.purchaseData.currentPeriod[1])
})
const currentAmount = this.purchaseData.currentAmount || 0
this.currentLvlPeriod = this.lvlPeriods.find((item) => item.start <= currentAmount && currentAmount <= (item.end || Infinity))!
this.purchaseData.$loading = false;
});
},
});
} }
qrCodeClick() { qrCodeClick() {
@ -63,26 +131,50 @@ export class GuestCardComponent implements OnInit {
} }
getPurchases( getPurchases(
start: Date | Moment = moment().startOf('month'), start: Date | Moment = moment().subtract(1, 'months').startOf('month'),
end: Date | Moment = moment() end: Date | Moment = moment()
): Observable<any> { ): Observable<any> {
const token = this.cookiesService.getItem('token'); const token = this.cookiesService.getItem('token');
const delta = moment(end).diff(moment(start), 'days'); const delta = moment(end).diff(moment(start), 'days');
return this.wpJsonService.getTransactionsInfo( return this.wpJsonService.getTransactions(
environment.systemId, environment.systemId,
token ?? '', token ?? '',
environment.icardProxy environment.icardProxy
); );
} }
getBalanceAmount(loyaltyPrograms: any[]) { getCurrentQuarterOfYear() {
console.log(loyaltyPrograms); const quarters = [
[
moment().subtract(1, 'years').endOf('year').subtract(3, 'months'),
moment().subtract(1, 'years').endOf('year'),
],
[moment().startOf('year'), moment().startOf('year').add(3, 'months')],
[
moment().startOf('year').add(3, 'months'),
moment().startOf('year').add(6, 'months'),
],
[
moment().startOf('year').add(6, 'months'),
moment().startOf('year').add(9, 'months'),
],
[
moment().startOf('year').add(9, 'months'),
moment().startOf('year').add(12, 'months'),
],
];
return loyaltyPrograms.reduce( for (let i = 0; i < 4; i++) {
(accumulator, currentValue) => { if (moment().isBetween(quarters[i][0], quarters[i][1])) {
return accumulator + currentValue.balance this.purchaseData.lastPeriod = quarters[i - 1];
}, this.purchaseData.currentPeriod = quarters[i];
0 }
); }
}
getBalanceAmount(loyaltyPrograms: any[]) {
return loyaltyPrograms.reduce((accumulator, currentValue) => {
return accumulator + currentValue.balance;
}, 0);
} }
} }