Compare commits

..

11 commits

26 changed files with 466 additions and 567 deletions

View file

@ -3,9 +3,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.2.0]
## [2.3.0]
## Added
### Changed
- Modified order to handle new `token` field.
- Modified order service to query API using `token`.
- Modified receipt component to use the new `token`.
- Modified invoice component to use the new `token`.
- Modified payment service component to remove order-creation logic.
### Fixed
- Receipt prompt textarea is now read-only.
- Invoice prompt textarea is now read-only.
- Button text color is now correct for Invoice and Receipt.
## [2.2.0] - 2023-05-15
### Added
- New API calls for requesting language data for login page

View file

@ -1,6 +1,6 @@
{
"name": "zgo",
"version": "2.2.0",
"version": "2.3.0",
"scripts": {
"ng": "ng",
"start": "ng serve",

View file

@ -45,7 +45,7 @@
style="margin-top: 10px;
margin-bottom: 20px;">
<div >&copy; 2023 Vergara Technologies LLC</div>
<div class="tiny">Version 2.2.0</div>
<div class="tiny">Version 2.3.0</div>
<div class="tiny">{{ vE.mainPriceData }}</div>
</div>
<div></div>

View file

@ -89,14 +89,14 @@
</tr>
</table>
<div style="height: 15px;"></div>
<div width="100%"
<div *ngIf="!order.paid" width="100%"
style="font-size: 14px;
font-weight: 700;
font-style: italic;
text-align: center;">
{{ vE.invoiceScanQrcode }}
</div>
<div style="text-align: center;
<div *ngIf="!order.paid" style="text-align: center;
margin-top: 10px;
line-height: 30px;">
<div style="font-family: 'Spartan';

View file

@ -9,7 +9,6 @@ import { faCheck, faHourglass, faArrowUpRightFromSquare } from '@fortawesome/fre
import { NotifierService } from '../notifier.service';
import { LanguageService } from '../language.service';
import { LanguageData } from '../language.model';
var QRCode = require('easyqrcodejs');
var URLSafeBase64 = require('urlsafe-base64');
@ -26,6 +25,7 @@ export class InvoiceComponent implements OnInit {
faHourglass = faHourglass;
faArrowUpRightFromSquare = faArrowUpRightFromSquare;
orderId;
orderToken: string = '';
public orderUpdate: Observable<Order>;
public nameUpdate: Observable<string>;
name: string = '';
@ -48,6 +48,7 @@ export class InvoiceComponent implements OnInit {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,
@ -98,10 +99,9 @@ export class InvoiceComponent implements OnInit {
private languageService : LanguageService
) {
this.orderId = this._ActiveRoute.snapshot.paramMap.get("orderId");
console.log('constructor - orderId -> ' + this.orderId);
this.orderUpdate = receiptService.orderUpdate;
this.nameUpdate = receiptService.nameUpdate;
receiptService.getOrderById(this.orderId!).subscribe(response => {
this._ActiveRoute.queryParams.subscribe((params) => {
this.orderToken = params["token"];
receiptService.getOrderById(this.orderId!, this.orderToken!).subscribe(response => {
if (response.status == 200){
this.error = false;
if( response.body!.order.session.substring(0,1) == 'X') {
@ -125,6 +125,10 @@ export class InvoiceComponent implements OnInit {
this.codeString = 'Test';
}
});
});
//console.log('constructor - orderId -> ' + this.orderId);
this.orderUpdate = receiptService.orderUpdate;
this.nameUpdate = receiptService.nameUpdate;
this.orderUpdate.subscribe(order => {
this.order = order;
if ( order.session.substring(0,1) == 'W') {

View file

@ -22,6 +22,8 @@ export class LanguageService {
private loginURL = ConfigData.Be_URL + 'getloginlang';
private mainURL = ConfigData.Be_URL + 'getmainlang';
private scanURL = ConfigData.Be_URL + 'getscanlang';
private invoiceURL = ConfigData.Be_URL + 'getinvoicelang';
private pmtservURL = ConfigData.Be_URL + 'getpmtservicelang';
public zgoLanguage: string = '';
@ -58,6 +60,10 @@ export class LanguageService {
return this.http.get<LanguageData>(this.mainURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else if (viewName === 'scan') {
return this.http.get<LanguageData>(this.scanURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else if (viewName === 'invoice') {
return this.http.get<LanguageData>(this.invoiceURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else if (viewName === 'pmtservice') {
return this.http.get<LanguageData>(this.pmtservURL + '/?lang=' + this.zgoLanguage, {headers: reqHeaders, params: params});
} else {
return this.http.get<LanguageData>(this.baseURL +
'/?lang=' + this.zgoLanguage +

View file

@ -129,8 +129,8 @@ img.icon{
.minibutton {
font-family: 'Spartan', sans-serif;
font-size: 14px;
background: #ff5722;
color: white;
/*background: #ff5722;*/
/*color: white;*/
height: 24px;
line-height: 20px;
padding: 10px;

View file

@ -162,10 +162,10 @@
padding-right: 20%;
margin-top: 10px;">
<span>
<button mat-stroked-button class="minibutton" color="primary" (click)="invoice(order)">{{ vE.listordersInvoiceBtn }}</button>
<button mat-raised-button class="minibutton" color="primary" (click)="invoice(order)">{{ vE.listordersInvoiceBtn }}</button>
</span>
<span>
<button mat-stroked-button class="minibutton" color="primary" (click)="receipt(order)">{{ vE.listordersReceiptBtn }}</button>
<button mat-raised-button class="minibutton" color="primary" (click)="receipt(order)">{{ vE.listordersReceiptBtn }}</button>
</span>
</div>
</mat-expansion-panel>

View file

@ -173,7 +173,8 @@ export class ListOrdersComponent implements OnInit, OnDestroy{
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
orderId: order._id
orderId: order._id,
orderToken: order.token
};
const dialogRef = this.dialog.open(PromptInvoiceComponent, dialogConfig);
@ -194,7 +195,8 @@ export class ListOrdersComponent implements OnInit, OnDestroy{
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
orderId: order._id
orderId: order._id,
orderToken: order.token
};
const dialogRef = this.dialog.open(PromptReceiptComponent, dialogConfig);

View file

@ -47,6 +47,7 @@ export class OrderComponent implements OnInit{
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,
@ -213,7 +214,8 @@ export class OrderComponent implements OnInit{
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
orderId: this.order._id
orderId: this.order._id,
orderToken: this.order.token
};
//console.log ('order_id : ' + this.order._id);

View file

@ -13,5 +13,6 @@ export interface Order {
lines: LineItem[],
paid: boolean,
externalInvoice: string,
shortCode: string
shortCode: string,
token: string
}

View file

@ -55,6 +55,7 @@ export class OrderService {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,
@ -159,6 +160,7 @@ export class OrderService {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [lineItem]
};
let obs = this.http.post<{message: string, order: Order}>(this.beUrl+'api/order', {payload: order}, { headers: this.reqHeaders, params: this.reqParams });
@ -188,6 +190,7 @@ export class OrderService {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,
@ -223,6 +226,7 @@ export class OrderService {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,

View file

@ -24,11 +24,11 @@
<div style="height: 50px;">
</div>
<div style="font-weight: 700;
font-size: 25px;
fonT-size: 25px;
text-align: center;">
{{ vE.pmtservicePmtsrvNot }}<br>
{{ vE.pmtserviceEnabledFor }}<br>
{{ owner.name}}
{{ shop }}
</div>
<div style="height: 40px;">
</div>
@ -131,7 +131,7 @@
</div>
<div class="invoiceDetail"
*ngIf="reportType==0"
id="invoice">
>
<div class="invoiceHdrTxt1">{{ vE.pmtserviceHdrTxt1 }}</div>
<div class="invoiceHdrTxt2">{{ vE.pmtserviceHdrTxt2 }}{{orderId}}</div>
<div class="invoiceHdrTxt3">{{ vE.pmtserviceHdrTxt3 }}{{order.timestamp | date}}
@ -206,7 +206,7 @@
</td>
<td width="25%">
<div style="text-align: right;"
id="payment-qr"
id="invoice-qr"
*ngIf="!order.paid"></div>
</td>
</tr>

View file

@ -4,8 +4,6 @@ import { HttpClient, HttpParams, HttpHeaders } from "@angular/common/http";
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { PmtData } from "./pmtservice.model";
import { XeroInvoice } from "./xeroinvoice.model";
import { Owner } from '../owner.model';
// import { Item } from '../items/item.model'
import { Order } from '../order/order.model'
import { ConfigData } from '../configdata';
import { faCheck, faHourglass } from '@fortawesome/free-solid-svg-icons';
@ -32,6 +30,7 @@ export class PmtserviceComponent implements OnInit {
beUrl = ConfigData.Be_URL;
private reqHeaders: HttpHeaders = new HttpHeaders();
public shop: string = '';
public pmtData : PmtData = {
ownerId :'',
invoice: '',
@ -54,23 +53,6 @@ export class PmtserviceComponent implements OnInit {
inv_ProcDate : new Date()
};
public owner: Owner = {
_id: '',
address: '',
name: '',
currency: 'usd',
tax: false,
taxValue: 0,
vat: false,
vatValue: 0,
paid: false,
zats: false,
invoices: false,
expiration: new Date(Date.now()).toISOString(),
payconf: false,
crmToken: '',
viewkey: ''
};
public order: Order = {
_id : '',
@ -85,6 +67,7 @@ public order: Order = {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,
@ -97,10 +80,10 @@ public order: Order = {
private invData_raw : string = '';
private invData_buff : any = null;
public reportType = 1000;
public reportType = 0;
public Status = 0;
codeString: string = '';
codeString: string = 'ZGo - The Zcash Register';
zcashUrl: SafeUrl = '';
zPrice: number = 1.0;
name: string = '';
@ -155,15 +138,13 @@ vE = {
private http : HttpClient,
private sanitizer: DomSanitizer,
private notifierService : NotifierService,
private languageService : LanguageService ) {}
ngOnInit() {
private languageService : LanguageService ){
var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64');
this.reqHeaders = new HttpHeaders().set('Authorization', auth);
this.activatedRoute.queryParams.subscribe((params) => {
this.pmtData.ownerId = params["owner"];
this.pmtData.invoice = params["invoiceNo"];
this.pmtData.amount = params["amount"];
this.pmtData.amount = +params["amount"];
this.pmtData.currency = params["currency"];
this.pmtData.shortcode = params["shortCode"];
this.getInvoiceData( this.pmtData );
@ -171,174 +152,28 @@ vE = {
this.chgUILanguage();
}
ngOnInit() {
}
getInvoiceData( reqData : PmtData ) {
//
// Verify owner id ( Status = 1 if not exists )
// ( Status = 2 if service not available for user )
//
// console.log('getOwner -> '+ reqData.ownerId);
// console.log('received amount -> ' + reqData.amount);
const ownParams = new HttpParams().append('id', reqData.ownerId);
let obs = this.http.get<{message:string, owner: any}>
( this.beUrl+'api/ownerid',
{ headers: this.reqHeaders,
params: ownParams,
observe: 'response'});
obs.subscribe((OwnerDataResponse) => {
//console.log('api/getowner', OwnerDataResponse.status);
if (OwnerDataResponse.status == 200) {
this.owner = OwnerDataResponse.body!.owner;
console.log('Owner => ' + this.owner.name );
//
// ==> remove "== false" for production enviroment
//
if ( this.owner.invoices ) {
// process data
console.log("Owner check passed!!!");
this.getXeroInvoiceData( reqData );
} else {
console.log("Owner check failed!!!")
this.reportType = 2;
};
} else {
if ( OwnerDataResponse.status == 204 ) {
console.log('Res.Status = ' + OwnerDataResponse.status)
console.log('Owner id not found!!!');
this.reportType = 1;
}
}});
}
getXeroInvoiceData( reqData : PmtData ) {
/*
// Call test Xero API
let url : string = "http://localhost:3000/xero/" + reqData.invoice;
this.http
.get<any>(url)
*/
console.log('>> find current zcash price');
this.getPrice(this.owner.currency);
console.log('get Invoice -> ' + reqData.invoice);
let invParams = new HttpParams();
invParams = invParams.append('address', this.owner.address);
invParams = invParams.append('inv', reqData.invoice);
let inv = this.http.get<{message:string, invData: any}>
( this.beUrl+'api/invdata',
{ headers: this.reqHeaders,
params: invParams,
observe: 'response'});
inv.subscribe( invDataResponse => {
// console.log('Response from ZGo-Xero');
// console.log(invDataResponse.status);
this.invData_buff = invDataResponse.body;
this.invData.inv_Type = this.invData_buff.invdata.inv_Type;
this.invData.inv_Id = this.invData_buff.invdata.inv_Id;
this.invData.inv_No = this.invData_buff.invdata.inv_No;
this.invData.inv_Contact = this.invData_buff.invdata.inv_Contact;
this.invData.inv_Currency = this.invData_buff.invdata.inv_Currency;
this.invData.inv_CurrencyRate = this.invData_buff.invdata.inv_CurrencyRate;
this.invData.inv_Total = this.invData_buff.invdata.inv_Total;
this.invData.inv_Status = this.invData_buff.invdata.inv_Status;
this.invData.inv_Date = this.invData_buff.invdata.inv_Date;
this.invData.inv_shortCode = reqData.shortcode;
/*
console.log('>>> inv_Type -> ' + this.invData.inv_Type);
console.log('>>> inv_Id -> ' + this.invData.inv_Id);
console.log('>>> inv_No -> ' + this.invData.inv_No);
console.log('>>> inv_Contact -> ' + this.invData.inv_Contact);
console.log('>>> inv_Currency-> ' + this.invData.inv_Currency);
console.log('>>> inv_CurrencyRate -> ' + this.invData.inv_CurrencyRate);
console.log('>>> inv_Total -> ' + this.invData.inv_Total);
console.log('>>> inv_Status-> ' + this.invData.inv_Status);
console.log('>>> inv_Date -> ' + this.invData.inv_Date);
*/
if ( this.invData.inv_Type == 'ACCREC' ) {
console.log('Invoice type is correct!!');
// Test if invoice is not already paid
if ( this.invData.inv_Status == 'AUTHORISED') {
console.log('invoice is payable');
// Test if Invoice's currency is supported
if ( this.invData.inv_Currency == reqData.currency ) {
console.log('Invoice currency supported');
// Test if requested amount is as reported by Xero
if ( this.invData.inv_Total == reqData.amount ) {
console.log('Invoice amount Ok - create Order');
// =====> Create order here
this.createOrder();
//
} else {
console.log('Invoice amount does not match')
this.reportType = 8;
}
} else {
console.log('Invoice currency not supported');
this.reportType = 7;
}
} else {
console.log('Invoice already paid');
this.reportType = 6;
}
} else {
console.log('Invoice type is invalid' );
this.reportType = 5;
}
},
error => {
console.log("Error while getting invData!!!");
console.log(error);
console.log(error.status);
if ( error.status == 500 ) {
// Assume that invoice was not found by haskell server
this.reportType = 4;
}
});
}
createOrder() {
this.reportType = 0;
// console.log('Starting order generation');
// console.log('>> find current zcash price');
this.order = {
_id: '',
address: this.owner.address,
session: 'Xero-' + this.owner._id,
currency: this.owner.currency,
timestamp: new Date(Date.now()).toISOString(),
closed: true,
totalZec: this.invData.inv_Total/this.zPrice,
price: this.zPrice,
total: this.invData.inv_Total,
paid: false,
externalInvoice: this.invData.inv_No,
shortCode: this.invData.inv_shortCode,
lines: [{qty: 1,
name: 'Invoice from ' + this.owner.name + '[' + this.invData.inv_No + ']',
cost: this.invData.inv_Total}]
};
let obs = this.http.post<{message: string, order: Order}>
(this.beUrl+'api/orderx',
{payload: this.order},
{ headers: this.reqHeaders }
//this.getXeroInvoiceData( reqData );
let obs = this.http.post<{reportType: number, order: Order, shop: string}>
(this.beUrl+'invdata',
{payload: reqData},
{headers: this.reqHeaders, observe: 'response' }
);
obs.subscribe((orderData) => {
// console.log('Order created');
// console.log(orderData.order);
this.order = orderData.order
console.log('>> order -> ' + JSON.stringify(this.order));
obs.subscribe((invoiceData) => {
if(invoiceData.status == 201) {
this.reportType = invoiceData.body!.reportType;
this.order = invoiceData.body!.order;
this.shop = invoiceData.body!.shop;
this.orderId = String(this.order._id);
// console.log('Generating QRCode....')
this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId).concat(' Invoice: ').concat(orderData.order.externalInvoice)))}`;
this.codeString = `zcash:${this.order.address}?amount=${this.order.totalZec.toFixed(8)}&memo=${URLSafeBase64.encode(Buffer.from('ZGo Order::'.concat(this.orderId).concat(' Invoice: ').concat(this.order.externalInvoice)))}`;
var qrcode = new QRCode(document.getElementById("payment-qr"), {
var qrcode = new QRCode(document.getElementById("invoice-qr"), {
text: this.codeString,
logo: "/assets/zcash.png",
width: 180,
@ -349,9 +184,10 @@ vE = {
});
this.zcashUrl = this.sanitizer.bypassSecurityTrustUrl(this.codeString);
}, error => {
console.log(error.message);
} else {
this.reportType = invoiceData.body!.reportType;
console.log('reportType ' + invoiceData.body!.reportType + ' code ' + invoiceData.status);
}
});
}
@ -362,22 +198,6 @@ vE = {
}
getPrice(currency: string){
//var currency = 'usd';
const params = new HttpParams().append('currency', currency);
let obs = this.http.get<{message: string, price: any}>(this.beUrl+'api/price', { headers:this.reqHeaders, params: params, observe: 'response'});
obs.subscribe((PriceData) => {
if (PriceData.status == 200) {
this.zPrice = PriceData.body!.price.price;
console.log("price", this.zPrice);
} else {
console.log('No price found for currency', currency);
this.zPrice = 1.0;
}
});
return obs;
}
copyAddress() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");
@ -398,6 +218,7 @@ vE = {
// console.error("Error", err);
}
}
copyAmount() {
if (!navigator.clipboard) {
// alert("Copy functionality not supported");

View file

@ -20,13 +20,13 @@
style="text-align: left;"
width="94%">
<div>
<textarea
<textarea matInput readonly
style="border: none;
outline: none;
width: 95%;"
cdkTextareaAutosize
cdkAutosizeMinRows="1"
cdkAutosizeMaxRows="4">{{ invoiceUrl }}
cdkAutosizeMaxRows="5">{{ invoiceUrl }}
</textarea>
</div>

View file

@ -18,6 +18,7 @@ var Buffer = require('buffer/').Buffer;
export class PromptInvoiceComponent implements OnInit {
orderId: string;
orderToken: string = '';
invoiceUrl: string;
// ------------------------------------
//
@ -41,10 +42,11 @@ export class PromptInvoiceComponent implements OnInit {
constructor(
private languageService : LanguageService,
private dialogRef: MatDialogRef<PromptInvoiceComponent>,
@Inject(MAT_DIALOG_DATA) public data: {orderId: string},
@Inject(MAT_DIALOG_DATA) public data: {orderId: string, orderToken: string},
private notifierService : NotifierService ) {
this.orderId = data.orderId;
this.invoiceUrl = 'https://app.zgo.cash/invoice/'+this.orderId;
this.orderToken = data.orderToken;
this.invoiceUrl = 'https://app.zgo.cash/invoice/'+this.orderId + '?token=' + this.orderToken;
}
ngOnInit(): void {

View file

@ -21,13 +21,13 @@
style="text-align: left;"
width="94%">
<div>
<textarea
<textarea matInput readonly
style="border: none;
outline: none;
width: 95%;"
cdkTextareaAutosize
cdkAutosizeMinRows="1"
cdkAutosizeMaxRows="4">{{ receiptUrl }}
cdkAutosizeMaxRows="5">{{ receiptUrl }}
</textarea>
</div>

View file

@ -19,6 +19,7 @@ var Buffer = require('buffer/').Buffer;
export class PromptReceiptComponent implements OnInit {
orderId: string;
orderToken: string;
receiptUrl: string;
// ------------------------------------
@ -43,10 +44,11 @@ export class PromptReceiptComponent implements OnInit {
constructor(
private languageService : LanguageService,
private dialogRef: MatDialogRef<PromptReceiptComponent>,
@Inject(MAT_DIALOG_DATA) public data: {orderId: string},
@Inject(MAT_DIALOG_DATA) public data: {orderId: string, orderToken: string},
private notifierService : NotifierService ) {
this.orderId = data.orderId;
this.receiptUrl = 'https://app.zgo.cash/receipt/'+this.orderId;
this.orderToken = data.orderToken;
this.receiptUrl = 'https://app.zgo.cash/receipt/' + this.orderId + '?token=' + this.orderToken;
}

View file

@ -14,7 +14,8 @@ var Buffer = require('buffer/').Buffer;
})
export class ReceiptService {
beUrl = ConfigData.Be_URL;
private dataStore: {order: Order, owner: Owner } = {
private dataStore: {order: Order, owner: Owner, name: string } = {
name: '',
owner: {
_id: '',
name: '',
@ -44,6 +45,7 @@ export class ReceiptService {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,
@ -57,34 +59,30 @@ export class ReceiptService {
public readonly orderUpdate: Observable<Order> = this._orderUpdated.asObservable();
public _nameUpdated: BehaviorSubject<string> = new BehaviorSubject(this.dataStore.owner.name);
public readonly nameUpdate: Observable<string>= this._nameUpdated.asObservable();
public readonly ownerUpdate;
//public readonly ownerUpdate;
private reqHeaders: HttpHeaders;
private session: null|string;
private params: HttpParams;
constructor(
private http: HttpClient,
public userService: UserService
) {
this.session = localStorage.getItem('s4z_token');
this.params = new HttpParams().append('session', this.session!);
//this.session = localStorage.getItem('s4z_token');
this.params = new HttpParams();
var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64');
this.reqHeaders = new HttpHeaders().set('Authorization', auth);
this.ownerUpdate = userService.ownerUpdate;
//this.ownerUpdate = userService.ownerUpdate;
}
getOrderById(id:string) {
let obs = this.http.get<{message: string, order: any}>(this.beUrl+'api/order/'+id, { headers:this.reqHeaders, params: this.params, observe: 'response'});
getOrderById(id:string, token: string) {
let obs = this.http.get<{message: string, order: any, shop: string}>(this.beUrl+'order/'+id, { headers:this.reqHeaders, params: this.params.append("token", token), observe: 'response'});
obs.subscribe((OrderDataResponse) => {
if (OrderDataResponse.status == 200) {
this.dataStore.order = OrderDataResponse.body!.order;
this.dataStore.name = OrderDataResponse.body!.shop;
this._orderUpdated.next(Object.assign({}, this.dataStore).order);
this.userService.getOwner();
this.ownerUpdate.subscribe((owner) => {
this.dataStore.owner = owner;
this._nameUpdated.next(Object.assign({}, this.dataStore).owner.name);
});
this._nameUpdated.next(Object.assign({}, this.dataStore).name);
} else {
this._orderUpdated.next(Object.assign({}, this.dataStore).order);
console.log('No order found');

View file

@ -14,6 +14,7 @@ import { LanguageData } from '../language.model';
})
export class ReceiptComponent implements OnInit {
orderId;
orderToken: string = '';
public orderUpdate: Observable<Order>;
public nameUpdate: Observable<string>;
name: string = '';
@ -30,6 +31,7 @@ export class ReceiptComponent implements OnInit {
paid: false,
externalInvoice: '',
shortCode: '',
token: '',
lines: [
{
qty: 1,
@ -60,12 +62,15 @@ export class ReceiptComponent implements OnInit {
public receiptService: ReceiptService
) {
this.orderId = this._ActiveRoute.snapshot.paramMap.get("orderId");
this._ActiveRoute.queryParams.subscribe((params) => {
this.orderToken = params["token"];
receiptService.getOrderById(this.orderId!, this.orderToken!);
});
this.orderUpdate = receiptService.orderUpdate;
this.nameUpdate = receiptService.nameUpdate;
receiptService.getOrderById(this.orderId!);
this.orderUpdate.subscribe(order => {
this.order = order;
});
this.nameUpdate = receiptService.nameUpdate;
this.nameUpdate.subscribe(name => {
this.name = name;

View file

@ -42,7 +42,7 @@
<mat-form-field class="full-width"
appearance="fill">
<mat-label>{{ vE.settingsVkeyLbl }}</mat-label>
<textarea matInput placeholder="{{ vE.settingsVkeyPlaceholder }}"
<textarea matInput [readonly]="vKaccess" placeholder="{{ vE.settingsVkeyPlaceholder }}"
formControlName="vKey">
</textarea>
</mat-form-field>

View file

@ -1,5 +1,5 @@
import { Inject, Component, OnInit, OnDestroy, ViewEncapsulation } from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
import { UntypedFormBuilder, Validators, UntypedFormGroup, FormControl } from '@angular/forms';
import { Subject, Observable } from 'rxjs';
@ -11,7 +11,6 @@ import { NotifierService } from '../notifier.service';
import { faCopy } from '@fortawesome/free-solid-svg-icons';
import { LanguageService } from '../language.service';
import { LanguageData } from '../language.model';
@Component({
selector: 'app-settings',
@ -30,7 +29,6 @@ export class SettingsComponent implements OnInit {
owner: Owner;
useZats: boolean;
proVersion: boolean = false;
useVKey: boolean = false;
linkMsg: string = '';
xeroAccCod: string = '';
saveAccOk: boolean = false;
@ -118,6 +116,7 @@ export class SettingsComponent implements OnInit {
};
//
languageRdy = new Subject<boolean>();
vKaccess = true;
// ------------------------------------------------------------
constructor(
@ -129,13 +128,11 @@ export class SettingsComponent implements OnInit {
private dialogRef: MatDialogRef<SettingsComponent>,
@Inject(MAT_DIALOG_DATA) public data: {o: Owner}) {
this.useZats = data.o.zats;
this.useVKey = data.o.payconf;
this.settingsForm = fb.group({
name: [data.o.name, Validators.required],
currency: [data.o.currency, Validators.required],
useZats: [data.o.zats, Validators.required],
useVKey: [data.o.payconf, Validators.required],
// proVersion: [data.invoices, Validators.required],
vKey: [data.o.viewkey]
});
this.accCodForm = fb.group ({
@ -143,7 +140,8 @@ export class SettingsComponent implements OnInit {
});
if (data.o.payconf) {
this.settingsForm.get('vKey')!.enable();
this.vKaccess = false;
//this.settingsForm.get('vKey')!.enable();
}
this.owner = data.o;
this.viewkey = data.o.viewkey;
@ -158,7 +156,7 @@ export class SettingsComponent implements OnInit {
this.xeroLink = `https://login.xero.com/identity/connect/authorize?response_type=code&client_id=${this.clientId}&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Fxeroauth&scope=accounting.transactions offline_access&state=${this.owner.address.substring(0, 6)}`
});
this.accCodeUpdate = xeroService.accCodeUpdate;
xeroService.getXeroAccountCode(this.owner.address);
xeroService.getXeroAccountCode();
this.accCodeUpdate.subscribe(accData => {
this.xeroAccCod = accData;
//console.log("xeroAccCod -> [" + this.xeroAccCod + "]");
@ -182,8 +180,9 @@ export class SettingsComponent implements OnInit {
ngOnInit() {
this.settingsForm.get('vKey')!.disable();
//this.settingsForm.get('vKey')!.disable();
//
this.vKaccess = true;
this.chgUILanguage();
//console.log('SETTINGS: Return from chgUILanguage()');
//
@ -207,7 +206,7 @@ export class SettingsComponent implements OnInit {
close() {
this.dialogRef.close();
this.dialogRef.close(null);
}
closeIntegration() {
@ -224,8 +223,8 @@ export class SettingsComponent implements OnInit {
this.owner.currency = this.settingsForm.value.currency;
this.owner.zats = this.settingsForm.value.useZats;
this.owner.payconf = this.settingsForm.value.useVKey;
this.viewkey = this.settingsForm.value.vKey;
//this.owner.invoices = this.settingsForm.value.proVersion
this.owner.viewkey = this.settingsForm.value.vKey;
console.log('Settings component key: ' + this.owner.viewkey);
this.dialogRef.close(this.owner);
}
@ -241,12 +240,13 @@ export class SettingsComponent implements OnInit {
// console.log("Viewing key switch is " +
// ( ob.checked ? "[ON]." : "[OFF]." ) );
this.useVKey = ob.checked;
if ( ob.checked )
this.settingsForm.get('vKey')!.enable();
else
this.settingsForm.get('vKey')!.disable();
if ( ob.checked ) {
//this.settingsForm.get('vKey')!.enable();
this.vKaccess = false;
} else {
//this.settingsForm.get('vKey')!.disable();
this.vKaccess = true;
}
}

View file

@ -162,6 +162,10 @@ export class UserService{
}
saveOwnerSettings(o: Owner) {
console.log('saveOwnerSettings: ' + o.viewkey);
if(o.viewkey.length > 20) {
this.saveOwnerViewingKey(o.viewkey).subscribe({
next: () => {
let obs = this.http.post(this.beUrl + 'api/ownersettings', {payload: o}, {headers: this.reqHeaders, params: this.reqParams});
obs.subscribe({
next: () => {
@ -172,7 +176,40 @@ export class UserService{
this.notifierService.showNotification("Saving settings failed", "Close", "error")
}
}
})
});
}
});
} else {
let obs = this.http.post(this.beUrl + 'api/ownersettings', {payload: o}, {headers: this.reqHeaders, params: this.reqParams});
obs.subscribe({
next: () => {
this.getOwner();
},
error: (error) => {
if ( error.status == 500 ){
this.notifierService.showNotification("Saving settings failed", "Close", "error")
}
}
});
}
}
saveOwnerViewingKey(vk: string){
let obs = this.http.post(this.beUrl + 'api/ownervk', {payload: vk}, {headers: this.reqHeaders, params: this.reqParams});
obs.subscribe({
next: () => {
this.getOwner();
},
error: (error) => {
if (error.status == 400) {
this.notifierService.showNotification('Invalid viewing key, changes not saved', 'Close', 'error');
} else if (error.status == 403) {
this.notifierService.showNotification('Viewing key does not match shop, changes not saved', 'Close', 'error');
}
}
});
return obs;
}
getOwner() {

View file

@ -24,7 +24,7 @@ export class XeroService {
savedAcc : boolean = false;
public savedAccObs = new Observable((observer) => {
console.log("starting savedAccObs");
//console.log("starting savedAccObs");
setTimeout(() => {observer.next(this.savedAcc)},1000);
})
@ -65,15 +65,14 @@ export class XeroService {
return obs;
}
getXeroAccessToken(code: string, address: string){
const params = this.reqParams.append('code', code).append('address', address);
getXeroAccessToken(code: string){
const params = this.reqParams.append('code', code);
let obs = this.http.get(this.beUrl + 'api/xerotoken' , {headers: this.reqHeaders, params: params, observe: 'response'});
return obs;
}
getXeroAccountCode(address: string){
const params = this.reqParams.append('address', address);
let obs = this.http.get<{message: string, code: string}>(this.beUrl + 'api/xeroaccount', {headers: this.reqHeaders, params: params, observe: 'response'});
getXeroAccountCode(){
let obs = this.http.get<{message: string, code: string}>(this.beUrl + 'api/xeroaccount', {headers: this.reqHeaders, params: this.reqParams, observe: 'response'});
obs.subscribe(accountResponse => {
if (accountResponse.status == 200) {
this.xeroAcc = accountResponse.body!.code;

View file

@ -77,7 +77,7 @@ export class XeroRegComponent implements OnInit {
this.activatedRoute.queryParams.subscribe((params) => {
//console.log(params);
if (params.state === this.owner.address.substring(0,6)) {
this.xeroService.getXeroAccessToken(params.code, this.owner.address).subscribe(tokenData => {
this.xeroService.getXeroAccessToken(params.code).subscribe(tokenData => {
if (tokenData.status == 200) {
//console.log(tokenData.body!);
this.flag = true;

View file

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Z-Go!</title>
<title>ZGo - The Zcash Register</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">