refs #5253 #22

Merged
juan merged 20 commits from test into master 2023-02-23 09:30:53 +00:00
23 changed files with 338 additions and 128 deletions
Showing only changes of commit 806c4cc3ad - Show all commits

View File

@ -5,8 +5,16 @@ export default new Class({
Template: require('./ui.xml'),
async open() {
const isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
if (isOk) await Hedera.Form.prototype.open.call(this);
await Hedera.Form.prototype.open.call(this);
let orderId = this.$.params.$.id;
if (!orderId)
orderId = localStorage.getItem('hederaBasket');
if (!orderId)
this.hash.setAll({form: 'ecomerce/pending'});
else
await Hedera.Basket.check(this.conn, this.hash);
this.$.params.set('id', orderId);
},
activate() {
@ -15,7 +23,17 @@ export default new Class({
onConfigureClick() {
Htk.Toast.showWarning(_('RememberReconfiguringImpact'));
this.hash.setAll({form: 'ecomerce/checkout'});
this.hash.setAll({
form: 'ecomerce/checkout',
id: this.$.params.$.id
});
},
onConfirmClick() {
this.hash.setAll({
form: 'ecomerce/confirm',
id: this.$.params.$.id
});
},
onDeleteClick(form) {

View File

@ -1,76 +1,94 @@
.basket .head {
border-bottom: 1px solid #DDD;
}
.basket .head p {
font-weight: bold;
margin: 0;
padding: 0;
font-size: 1.4rem;
text-align: right;
}
.basket .form > p {
margin: 0;
font-size: 1.4rem;
color: white;
text-align: right;
}
/* Lines */
.basket .line {
display: flex;
align-items: center;
gap: 12px;
margin: 10px 0;
height: 80px;
}
.basket .line:first-child {
margin-top: 0;
}
.basket .line:last-child {
margin-bottom: 0;
}
.basket .line > .delete {
margin: 0 -8px;
}
.basket .line > .photo {
flex: none;
border-radius: 50%;
width: 68px;
height: 68px;
gap: 0;
}
.basket .line > .info {
flex: 1;
overflow: hidden;
}
.basket .line > .info > * {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.basket .line > .info > h2 {
font-size: 1rem;
font-weight: normal;
margin: 0;
}
.basket .line > .info > p {
margin: 0;
}
.basket .line > .info > .tags {
color: #777;
}
.basket .line .subtotal {
float: right;
}
/* Fields */
.basket td.available-exceeded input {
background-color: #FCC;
}
.basket .icon > img {
border-radius: 50%;
.hedera-basket {
.head {
border-bottom: 1px solid #DDD;
& > div > div {
margin: 15px 0;
}
& > div > div:first-child {
margin: 0;
}
p {
margin: 3px 0;
&.important {
font-size: 1.2rem;
font-weight: bold;
}
}
.total {
font-weight: bold;
margin: 0;
padding: 0;
font-size: 1.4rem;
text-align: right;
}
}
.form > p {
margin: 0;
font-size: 1.4rem;
color: white;
text-align: right;
}
/* Lines */
.line {
display: flex;
align-items: center;
gap: 12px;
margin: 10px 0;
height: 80px;
}
.line:first-child {
margin-top: 0;
}
.line:last-child {
margin-bottom: 0;
}
.line > .delete {
margin: 0 -8px;
}
.line > .photo {
flex: none;
border-radius: 50%;
width: 68px;
height: 68px;
gap: 0;
}
.line > .info {
flex: 1;
overflow: hidden;
}
.line > .info > * {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.line > .info > h2 {
font-size: 1rem;
font-weight: normal;
margin: 0;
}
.line > .info > p {
margin: 0;
}
.line > .info > .tags {
color: #777;
}
.line .subtotal {
float: right;
}
/* Fields */
td.available-exceeded input {
background-color: #FCC;
}
.icon > img {
border-radius: 50%;
}
}

View File

@ -1,6 +1,9 @@
<vn>
<vn-lot-query id="params">
<vn-spec name="id" type="Number"/>
</vn-lot-query>
<div id="title">
<h1><t>ShoppingBasket</t></h1>
<h1>{{_(params.$.id ? 'Order' : 'ShoppingBasket')}}</h1>
</div>
<div id="actions">
<htk-bar-button
@ -14,12 +17,33 @@
<htk-bar-button
icon="shopping_cart_checkout"
tip="_Checkout"
on-click="this.hash.setAll({form: 'ecomerce/confirm'})"/>
on-click="this.onConfirmClick()"/>
</div>
<div id="form" class="basket">
<vn-group>
<db-form v-model="order">
<db-model property="model" lot="params">
SELECT o.id, o.sent,
ag.description agency, v.code method, ad.nickname
FROM myOrder o
JOIN vn.agencyMode ag ON ag.id = o.agencyModeFk
LEFT JOIN myAddress ad ON ad.id = o.addressFk
JOIN vn.deliveryMethod v ON v.id = o.deliveryMethodFk
WHERE o.id = #id;
</db-model>
</db-form>
</vn-group>
<div id="form" class="hedera-basket">
<div class="box vn-w-sm vn-pa-lg">
<div class="head vn-pb-lg">
<p>
<h5>#{{order.id}}</h5>
<div class="vn-mt-md">
<h6><t>ShippingInformation</t></h6>
<p></p>
<p><t>Delivery at</t> {{Vn.Value.format(order.sent, _('%D'))}}</p>
<p><span id="method"><t>Agency</t></span> {{order.agency}}</p>
<p>{{order.nickname}}</p>
</div>
<p class="total">
<t>Total</t>
<htk-text format="%.2d€">
<db-calc-sum property="param" func="subtotal" model="items"/>
@ -28,15 +52,16 @@
</div>
<div class="lines vn-pt-lg">
<htk-repeater form-id="iter">
<db-model id="items" property="model" updatable="true">
<db-model id="items" property="model" lot="params" updatable="true">
SELECT bi.id, bi.amount, bi.price, i.longName item,
i.tag5, i.value5, i.tag6, i.value6, i.tag7, i.value7,
i.image, im.updated
FROM myBasketItem bi
FROM myOrderRow bi
JOIN vn.item i ON i.id = bi.itemFk
LEFT JOIN image im
ON im.collectionFk = 'catalog'
AND im.name = i.image
WHERE orderFk = #id
</db-model>
<custom>
<div class="line">

View File

@ -10,7 +10,7 @@ const Catalog = new Class({
let isOk = true;
if (!localStorage.getItem('hederaGuest'))
isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
isOk = await Hedera.Basket.check(this.conn, this.hash);
else
await this.conn.execQuery('CALL mybasket_configureForGuest');

View File

@ -44,7 +44,7 @@ export default new Class({
}
this.$.lot.assign({
date: date,
date,
method: row.deliveryMethod,
agency: row.agencyModeFk,
address: row.addressFk
@ -59,11 +59,21 @@ export default new Class({
async onConfirmClick() {
this.disableButtons(true);
const query = 'CALL myBasket_configure(#date, #method, #agency, #address)';
const id = this.$.params.$.id;
const params = Object.assign({}, this.$.lot.$);
let query;
if (id) {
params.id = id;
query = 'CALL myOrder_configure(#id, #date, #method, #agency, #address)';
} else {
query = 'CALL myOrder_create(@id, #date, #method, #agency, #address)';
}
let resultSet;
try {
resultSet = await this.conn.execQuery(query, this.$.lot.$);
resultSet = await this.conn.execQuery(query, params);
} finally {
this.disableButtons(false);
}
@ -71,7 +81,7 @@ export default new Class({
if (!resultSet.fetchResult())
return;
if (this.$.orderForm.numRows > 0)
if (id)
Htk.Toast.showMessage(_('OrderUpdated'));
else
Htk.Toast.showMessage(_('OrderStarted'));
@ -80,7 +90,7 @@ export default new Class({
},
onCancelClick() {
if (this.$.orderForm.numRows > 0)
if (this.$.params.$.id)
window.history.back();
else
this.hash.setAll({form: 'ecomerce/orders'});

View File

@ -1,4 +1,7 @@
<vn>
<vn-lot-query id="params">
<vn-spec name="id" type="Number"/>
</vn-lot-query>
<vn-group>
<vn-lot id="lot" on-change="this.onAddressChange()"/>
<db-form id="defaults" on-ready="onValuesReady">
@ -8,10 +11,11 @@
</db-model>
</db-form>
<db-form id="order-form" on-ready="onValuesReady">
<db-model property="model">
<db-model property="model" lot="params">
SELECT m.code deliveryMethod, o.sent, o.agencyModeFk, o.addressFk
FROM myBasket o
FROM myOrder o
JOIN vn.deliveryMethod m ON m.id = o.deliveryMethodFk
WHERE o.id = #id
</db-model>
</db-form>
<db-model id="agencies"

View File

@ -5,7 +5,7 @@ export default new Class({
Template: require('./ui.xml'),
async open() {
const isOk = await Hedera.BasketChecker.check(this.conn, this.hash);
const isOk = await Hedera.Basket.check(this.conn, this.hash);
if (isOk) await Hedera.Form.prototype.open.call(this);
},
@ -116,15 +116,16 @@ export default new Class({
},
async onConfirmClick() {
this.disableButtons(true);
await this.$.confirmQuery.execute();
},
onConfirm(query, resultSet) {
this.disableButtons(false);
if (resultSet.fetchResult())
Vn.Node.disableInputs(this.node);
try {
await this.conn.execQuery(
'CALL myOrder_confirm(#id)',
this.$.params.$
);
this.$.successDialog.show();
} finally {
Vn.Node.disableInputs(this.node, false);
}
},
async onDialogResponse() {

View File

@ -1,13 +1,16 @@
<vn>
<vn-lot-query id="params">
<vn-spec name="id" type="Number"/>
</vn-lot-query>
<vn-group>
<db-form v-model="order" on-ready="onOrderReady">
<db-model property="model" result-index="1">
CALL myBasket_getTax;
<db-model property="model" result-index="1" lot="params">
CALL myOrder_getTax(#id);
SELECT o.id, o.sent, o.notes, o.companyFk,
ag.description agency, v.code method,
ad.nickname, ad.postalCode, ad.city, ad.street,
t.*, c.credit, myClient_getDebt(NULL) debt
FROM myBasket o
FROM myOrder o
JOIN vn.agencyMode ag ON ag.id = o.agencyModeFk
LEFT JOIN myAddress ad ON ad.id = o.addressFk
JOIN vn.deliveryMethod v ON v.id = o.deliveryMethodFk
@ -17,7 +20,8 @@
IFNULL(SUM(taxableBase), 0) taxableBase,
IFNULL(SUM(tax), 0) tax
FROM tmp.orderAmount
) t;
) t
WHERE o.id = #id;
DROP TEMPORARY TABLE
tmp.orderAmount,
tmp.orderTax;
@ -37,7 +41,7 @@
<div class="delivery">
<h6><t>ShippingInformation</t></h6>
<p>
<t>Delivery at</t> {{Vn.Value.format(order.sent, _('%D'))}}
<t>Delivery at</t> {{Vn.Value.format(order.sent, _('%D'))}}
</p>
<p>
<span id="method"><t>Agency</t></span> {{order.agency}}

View File

@ -36,4 +36,3 @@
.orders .htk-list .total {
float: right;
}

View File

@ -0,0 +1,21 @@
import './style.scss';
export default new Class({
Extends: Hedera.Form,
Template: require('./ui.xml'),
activate() {
this.$.orders.setInfo('o', 'myOrder', 'hedera', ['id'], 'id');
},
async onRemoveOrderClick(form) {
if (confirm(_('AreYouSureDeleteOrder')))
await form.deleteRow();
},
loadOrder(id) {
localStorage.setItem('hederaBasket', id);
this.hash.setAll({form: 'ecomerce/catalog'});
Htk.Toast.showMessage(_('OrderLoadedIntoBasket'));
}
});

View File

@ -0,0 +1 @@
Pending: Pendents

View File

@ -0,0 +1 @@
Pending: Pending

View File

@ -0,0 +1,8 @@
Pending: Pendientes
PendingOrders: Pedidos pendientes
NewOrder: Nuevo pedido
ViewOrder: Ver pedido
RemoveOrder: Eliminar pedido
LoadOrderIntoCart: Cargar pedido en la cesta
AreYouSureDeleteOrder: ¿Seguro que quieres borrar el pedido?
OrderLoadedIntoBasket: ¡Pedido cargado en la cesta!

View File

@ -0,0 +1 @@
Pending: Pendents

View File

@ -0,0 +1 @@
Pending: Pendientes

View File

View File

@ -0,0 +1,54 @@
<vn>
<div id="title">
<h1><t>PendingOrders</t></h1>
</div>
<div id="actions">
<htk-bar-button
class="start-order"
icon="add_shopping_cart"
tip="_NewOrder"
on-click="hash.setAll({form: 'ecomerce/checkout'})"/>
</div>
<div id="form" class="hedera-pending">
<htk-repeater
class="htk-list box confirmed vn-w-sm"
form-id="iter">
<db-model property="model" id="orders">
SELECT o.id, o.sent, o.deliveryMethodFk, o.total,
a.nickname, am.description agency
FROM myOrder o
JOIN myAddress a ON a.id = o.addressFk
JOIN vn.agencyMode am ON am.id = o.agencyModeFk
WHERE NOT o.isConfirmed
ORDER BY o.sent DESC
</db-model>
<custom>
<a class="item"
title="{{_('ViewOrder')}}"
href="{{'#!form=ecomerce/basket&amp;id='+iter.id}}">
<div class="content">
<p class="important">
{{Vn.Value.format(iter.sent, '%D')}}
</p>
<p>#{{iter.id}}</p>
<p>{{iter.nickname}}</p>
<p>{{iter.agency}}</p>
<p>{{Vn.Value.format(iter.total, '%.2d€')}}</p>
</div>
<div
class="actions"
on-click="$event.preventDefault()">
<htk-button
icon="delete"
tip="_RemoveOrder"
on-click="this.onRemoveOrderClick($iter)"/>
<htk-button
icon="shopping_bag"
tip="_LoadOrderIntoCart"
on-click="this.loadOrder(iter.id)"/>
</div>
</a>
</custom>
</htk-repeater>
</div>
</vn>

View File

@ -70,7 +70,9 @@ export const routes = {
orders:
() => import('ecomerce/orders'),
ticket:
() => import('ecomerce/ticket')
() => import('ecomerce/ticket'),
pending:
() => import('ecomerce/pending')
},
news: {
new:

View File

@ -9,6 +9,24 @@ module.exports = new Class({
,get() {
return this._conn;
}
},
hash: {
type: Vn.Hash
,get() {
return this._hash;
}
},
gui: {
type: Gui
,get() {
return this._gui;
}
},
login: {
type: Login
,get() {
return this._login;
}
}
}
@ -35,6 +53,7 @@ module.exports = new Class({
,showLogin() {
const login = this._login = new Login({
app: this,
conn: this._conn,
hash: this._hash
});
@ -47,6 +66,7 @@ module.exports = new Class({
if (this._gui) return;
const gui = this._gui = new Gui({
app: this,
conn: this._conn,
hash: this._hash
});

View File

@ -1,21 +0,0 @@
module.exports = {
async check(conn, hash) {
this.hash = hash;
const resultSet = await conn.execQuery('CALL myBasket_check');
const status = resultSet.fetchValue();
if (!status) return;
const isOk = status == 'UPDATED' || status == 'OK';
if (status == 'UPDATED')
Htk.Toast.showWarning(_('Order items updated'));
if (!isOk)
this.hash.setAll({form: 'ecomerce/checkout'});
return isOk;
}
};

42
js/hedera/basket.js Normal file
View File

@ -0,0 +1,42 @@
module.exports = class {
constructor(app) {
this.app = app;
let orderId = localStorage.getItem('hederaBasket');
if (orderId) orderId = parseInt(orderId);
this.orderId = orderId;
}
async check(conn, hash) {
this.hash = hash;
const orderId = localStorage.getItem('hederaBasket');
const resultSet = await this.app.conn.execQuery(
'CALL myOrder_check(#id)',
{id: orderId}
);
const status = resultSet.fetchValue();
if (!status) return;
const isOk = status == 'updated' || status == 'ok';
if (status == 'updated')
Htk.Toast.showWarning(_('Order items updated'));
if (!isOk) {
const params = {form: 'ecomerce/checkout'};
if (orderId) params.id = orderId;
this.hash.setAll(params);
}
return isOk;
}
async load(orderId) {
if (this.orderId != orderId) {
localStorage.setItem('hederaBasket', orderId);
this.orderId = orderId;
}
await this.check()
}
};

View File

@ -7,6 +7,7 @@ module.exports = new Class({
,initialize(gui) {
this.gui = gui;
this.app = gui.app;
this.conn = gui.conn;
this.hash = gui.hash;
}

View File

@ -10,6 +10,6 @@ Hedera = module.exports = {
,Report : require('./report')
,App : require('./app')
,Tpv : require('./tpv')
,BasketChecker : require('./basket-checker')
,Basket : require('./basket')
};