- Categorie

- ProductInfo
This commit is contained in:
Surya Paolo
2023-12-27 02:58:23 +01:00
parent c27c293fbf
commit 6be8ccc906
30 changed files with 612 additions and 198 deletions

View File

@@ -16,6 +16,7 @@
.prod_disp {
font-size: 1.2rem;
font-size: 1.2rem;
}

View File

@@ -24,7 +24,7 @@ export default defineComponent({
required: false,
default: null,
},
code: {
id: {
type: String,
required: false,
default: '',
@@ -58,7 +58,9 @@ export default defineComponent({
quantity: 0,
quantitypreordered: 0,
idStorehouse: '',
idProvider: ''
idGasordine: '',
storehouse: {},
gasordine: {},
})
const storeSelected = ref('')
@@ -97,7 +99,7 @@ export default defineComponent({
return false
}
const ris = await products.addtoCartBase({ $q, t, code: myproduct.value.code!, order: myorder, addqty: add })
const ris = await products.addtoCartBase({ $q, t, id: myproduct.value._id, order: myorder, addqty: add })
updateproduct()
if (ris && ris.myord) {
@@ -140,7 +142,7 @@ export default defineComponent({
}
function updateproduct() {
myproduct.value = products.getProductByCode(props.code)
myproduct.value = products.getProductById(props.id)
// products.updateQuantityAvailable(myproduct.value._id)
}
@@ -214,8 +216,8 @@ export default defineComponent({
return ''
}
watch(() => props.code, (newval, oldval) => {
console.log('change code')
watch(() => props.id, (newval, oldval) => {
// console.log('change code')
load()
})
@@ -236,6 +238,7 @@ export default defineComponent({
if (!!myproduct.value) {
if (myproduct.value.storehouses && myproduct.value.storehouses.length === 1) {
// Se solo 1 presente, metto fisso l'unico negozio !
myorder.idStorehouse = myproduct.value.storehouses[0]._id
}
@@ -252,6 +255,10 @@ export default defineComponent({
if (ord.idGasordine)
gasordineSelected.value = ord.idGasordine!
// Seleziona il Negozio che avevo già scelto nell'ordine !
if (ord.idStorehouse)
storeSelected.value = ord.idStorehouse
}
}
@@ -274,13 +281,49 @@ export default defineComponent({
function enableAddQty() {
if (site.value.ecomm && site.value.ecomm.enablePreOrders) {
return getQtyBookableAvailable() > 0 || getQtyAvailable() > 0
return (getQtyBookableAvailable() > 0
&& (myproduct.value.maxBookableQty === 0
|| (myorder.quantitypreordered + 1 < myproduct.value.maxBookableQty))
)
|| (getQtyAvailable() > 0)
&& (myproduct.value.maxBookableQty === 0
|| (myorder.quantity + 1 < myproduct.value.maxBookableQty ))
} else {
return getQtyAvailable() > 0
return (getQtyAvailable() > 0)
&& (myproduct.value.maxBookableQty === 0
|| (myorder.quantity + 1 < myproduct.value.maxBookableQty ))
}
}
function qtaNextAdd() {
let step = 1
if (getQtyAvailable() > 0) {
if (myorder.quantity === 0)
step = myproduct.value.minBuyQty | 1
} else {
if (myorder.quantitypreordered === 0)
step = myproduct.value.minBuyQty | 1
}
return step
}
function qtaNextSub() {
let step = 1
let minqta = myproduct.value.minBuyQty | 1
if (getQtyAvailable() > 0) {
if (myorder.quantity === minqta)
step = minqta
} else {
if (myorder.quantitypreordered === minqta)
step = minqta
}
return step
}
function visuListDisponibili() {
openlistorders.value = true
sumval.value = products.getSumQtyOrderProductInOrdersCart(myproduct.value._id)
@@ -336,6 +379,8 @@ export default defineComponent({
listord,
sumval,
getGasordines,
qtaNextAdd,
qtaNextSub,
}
}
})

View File

@@ -2,10 +2,14 @@
<div class="q-pa-md row items-start q-gutter-md">
<q-spinner v-if="!endload" color="primary" size="3em" :thickness="2" />
<q-card :class="getmycardcl()" v-if="!!myproduct && endload" bordered>
<q-card
:class="getmycardcl()"
v-if="!!myproduct && endload && !!myproduct.productInfo"
bordered
>
<q-img
:src="`` + myproduct.img"
:alt="myproduct.name"
:src="`` + myproduct.productInfo.img"
:alt="myproduct.productInfo.name"
:class="getclimgproduct()"
></q-img>
@@ -18,22 +22,25 @@
icon="fas fa-info"
class="absolute semi-transparent"
style="top: 0; right: 12px; transform: translateY(-50%)"
:to="`/product/` + myproduct.code"
:to="`/product/` + myproduct._id + '/' + cosa"
/>
<div class="row items-center centeritems">
<div class="text-h7 boldhigh">
{{ myproduct.name }}
{{ myproduct.productInfo.name }}
</div>
<div class="product_code">
&nbsp; {{ $t('ecomm.codice') }}: {{ myproduct.code }}
&nbsp; {{ t('ecomm.codice') }}: {{ myproduct.productInfo.code }}
</div>
</div>
</q-item>
<q-item v-if="complete">
<q-item v-if="complete && myproduct.productInfo.description">
<div class="row items-center">
<div class="text-title text-grey-9">
<span class="text-grey-7" v-html="myproduct.description"></span>
<span
class="text-grey-7"
v-html="myproduct.productInfo.description"
></span>
</div>
</div>
</q-item>
@@ -66,20 +73,25 @@
</div>
</q-item-label>
</q-item-section>
<q-item-section avatar v-if="myproduct.weight">
<q-item-section avatar v-if="myproduct.productInfo.weight">
<q-icon
name="fas fa-balance-scale"
style="padding-right: 16px !important"
/>
</q-item-section>
<q-item-section v-if="myproduct.weight">
<q-item-section v-if="myproduct.productInfo.weight">
<q-item-label>
{{ t('products.weight') }}
</q-item-label>
<q-item-label>
<span class="text-black q-ml-xs text-h8" v-if="myproduct.unit">
{{ myproduct.weight }}
{{ tools.getUnitsMeasure(myproduct.unit, true) }}</span
<span
class="text-black q-ml-xs text-h8"
v-if="myproduct.productInfo.unit"
>
{{ myproduct.productInfo.weight }}
{{
tools.getUnitsMeasure(myproduct.productInfo.unit, true)
}}</span
>
</q-item-label>
</q-item-section>
@@ -93,8 +105,14 @@
<q-item-label>
{{ t('products.gasordine') }}
</q-item-label>
<q-item-label
v-if="(tools.isArray(myproduct.gasordines) && myproduct.gasordines.length > 1) && (!myorder.idGasordine || ((myorder.quantity + myorder.quantitypreordered) === 0 ))">
<q-item-label
v-if="
tools.isArray(myproduct.gasordines) &&
myproduct.gasordines.length > 1 &&
(!myorder.idGasordine ||
myorder.quantity + myorder.quantitypreordered === 0)
"
>
<q-select
:behavior="$q.platform.is.ios === true ? 'dialog' : 'menu'"
outlined
@@ -171,7 +189,7 @@
"
>
{{
$t('ecomm.qta_in_attesa', {
t('ecomm.qta_in_attesa', {
qty: myproduct.QuantitaOrdinateInAttesa,
})
}}
@@ -209,7 +227,7 @@
"
>
{{
$t('ecomm.qta_prenotate_in_attesa', {
t('ecomm.qta_prenotate_in_attesa', {
qty: myproduct.QuantitaPrenotateInAttesa,
})
}}
@@ -255,7 +273,7 @@
:disable="checkifCartDisable() || !enableSubQty()"
rounded
size="md"
:label="t('products.subcart', { qta: 1 })"
:label="t('products.subcart', { qta: qtaNextSub() })"
@click="addtoCart(false)"
>
</q-btn>
@@ -279,7 +297,7 @@
:disable="checkifCartDisable() || !enableAddQty()"
rounded
size="md"
:label="t('products.addcart', { qta: 1 })"
:label="t('products.addcart', { qta: qtaNextAdd() })"
@click="addtoCart(true)"
>
</q-btn>
@@ -291,7 +309,7 @@
rounded
icon="fas fa-shopping-cart"
color="primary"
:label="$t('ecomm.btn_cassa')"
:label="t('ecomm.btn_cassa')"
class="q-mb-sm"
to="/checkout"
></q-btn>
@@ -306,7 +324,7 @@
<q-card class="dialog_card">
<q-toolbar class="bg-primary text-white">
<q-toolbar-title>
{{ t('ecomm.listaord') }} - {{ myproduct.name }}
{{ t('ecomm.listaord') }} - {{ myproduct.productInfo.name }}
</q-toolbar-title>
<q-btn flat round color="white" icon="close" v-close-popup></q-btn>
</q-toolbar>

View File

@@ -6,6 +6,8 @@ import { IOperators, IOrder, IProduct } from '@src/model'
import { defineComponent, PropType, toRef } from 'vue'
import { CTitleBanner } from '@src/components/CTitleBanner'
import { useProducts } from '@store/Products'
import { useI18n } from '@src/boot/i18n'
import { useQuasar } from 'quasar'
export default defineComponent({
@@ -30,6 +32,9 @@ export default defineComponent({
setup(props) {
const products = useProducts()
const order = toRef(props, 'order')
const { t } = useI18n()
const $q = useQuasar()
function myimgclass() {
if (props.showall) {
@@ -71,14 +76,16 @@ export default defineComponent({
order: props.order,
}).then((res: any) => {
if (res.risult) {
order.value.quantity = res.myord.quantity
order.value.quantitypreordered = res.myord.quantitypreordered
if (res.myord) {
order.value.quantity = res.myord.quantity
order.value.quantitypreordered = res.myord.quantitypreordered
}
}
})
}
function isApplicatoSconto() {
const totalipotetico = order.value.price * (order.value.quantity + order.value.quantitypreordered)
const totalipotetico = order.value.product!.price * (order.value.quantity + order.value.quantitypreordered)
if (totalipotetico > order.value.TotalPriceProduct) {
return true
}
@@ -89,8 +96,8 @@ export default defineComponent({
products.removeFromCart({ order: order.value })
}
function getRisparmio(): string {
return ((order.value.price * order.value.quantity) - order.value.TotalPriceProduct).toFixed(2)
function getRisparmio(): string {
return ((order.value.product!.price * order.value.quantity) - order.value.TotalPriceProduct).toFixed(2)
}
return {
@@ -101,6 +108,7 @@ export default defineComponent({
getRisparmio,
tools,
products,
t,
}
},
})

View File

@@ -3,9 +3,9 @@
<div v-if="order.product" class="row items-center justify-evenly no-wrap">
<div class="col-2 text-h6 ellipsis">
<q-img
v-if="order.product && order.product.img"
:src="`` + order.product.img"
:alt="order.product.name"
v-if="order.product && order.product.productInfo.img"
:src="`` + order.product.productInfo.img"
:alt="order.product.productInfo.name"
:class="myimgclass"
>
</q-img>
@@ -14,7 +14,7 @@
<div v-if="order.idGasordine" class="gasordine">
{{ products.getSingleGasordine(order, true) }}<br>
</div>
{{ order.product.name }}
{{ order.product.productInfo.name }}
<!--<div v-if="showalle">
<br /><span class="text-grey">{{ order.product.description }}</span>
@@ -35,7 +35,7 @@
{{ order.quantity }}
</div>
<div v-if="order.quantity > 0 && order.quantitypreordered > 0">
+ {{ $t('ecomm.preord') }}:
+ {{ t('ecomm.preord') }}:
</div>
<div
@@ -55,10 +55,10 @@
</div>
<div
class="text-black q-ml-xs text-h8 text-center"
v-if="order.product.unit"
v-if="order.product.productInfo.unit"
>
{{ tools.getWeightTotalByOrder(order) }}
{{ tools.getUnitsMeasure(order.product.unit, true) }}
{{ tools.getUnitsMeasure(order.product.productInfo.unit, true) }}
</div>
</div>
<div class="col-2 no-wrap text-subtitle3_short q-mr-sm">

View File

@@ -31,11 +31,13 @@ const msg_website_it = {
producer: 'Produttore',
orderinfo: 'Ordini Effettuati',
products: 'Prodotti',
productInfos: 'Info Prodotti',
productslist: 'Lista Prodotti',
collabora: 'Collabora',
categories: 'Categorie',
storehouses: 'Magazzino',
providers: 'Fornitori',
catprods: 'Categorie',
gasordine: 'Gas Ordine',
scontisticas: 'Scontistica',
departments: 'Uffici',

View File

@@ -1,7 +1,7 @@
import { IAction } from '@src/model/Projects'
import { IFriends, IGroupShort, IMyGroup, IPaymentType } from '@src/model/UserStore'
import {
IDepartment, IProducer, IShareWithUs, IStorehouse, IProvider, IScontistica, ICategory, IGasordine
IDepartment, IProducer, IShareWithUs, IStorehouse, IProductInfo, IProvider, IScontistica, ICategory, IGasordine, ICatProd
} from '@src/model/Products'
import { IUserFields, IUserProfile } from '@src/model/UserStore'
@@ -442,6 +442,7 @@ export interface IGlobalState {
calzoom: ICalZoom[],
producers: IProducer[],
providers: IProvider[],
catprods: ICatProd[],
gasordines: IGasordine[],
scontisticas: IScontistica[],
storehouses: IStorehouse[],

View File

@@ -1,9 +1,29 @@
import { IUserFields } from './UserStore'
export interface IProductInfo {
_id?: any
code?: string,
name?: string,
description?: string,
department?: string,
idCatProds?: string[],
catprods?: ICatProd[],
color?: string,
size?: string,
weight?: number,
unit?: number,
stars?: number,
date?: Date,
icon?: string,
img?: string
}
export interface IProduct {
_id?: any
active?: boolean
idProductInfo?: string,
productInfo: IProductInfo,
idProducer?: string,
idProvider?: string,
idStorehouses?: string[],
@@ -14,30 +34,18 @@ export interface IProduct {
storehouses: IStorehouse[],
gasordines: IGasordine[],
provider?: IProvider,
code?: string,
name?: string,
description?: string,
department?: string,
category?: string,
price: number,
after_price?: string,
color?: string,
size?: string,
quantityAvailable?: number,
bookableAvailableQty?: number,
QuantitaOrdinateInAttesa?: number,
QuantitaPrenotateInAttesa?: number,
stockQty: number,
minBuyQty: number,
maxBookableQty: number,
bookableQty: number,
canBeShipped?: boolean,
canBeBuyOnline?: boolean,
weight?: number,
unit?: number,
stars?: number,
date?: Date,
icon?: string,
img?: string
}
export interface IBaseOrder {
@@ -50,25 +58,15 @@ export interface IOrder {
userId?: string
status?: number
idProduct?: string
idProducer?: string
idProvider?: string
idGasordine?: string
idStorehouse?: string
idScontisticas?: string[]
price: number
idGasordine?: string
TotalPriceProduct: number
price: number
after_price?: string
color?: string
size?: string
quantity: number
quantitypreordered: number
weight?: number
stars?: number
product?: IProduct
producer?: IProducer
storehouse?: IStorehouse
scontisticas?: IScontistica[]
provider?: IProvider
gasordine?: IGasordine
date_created?: Date
date_checkout?: Date
@@ -82,6 +80,8 @@ export interface IProductsState {
products: IProduct[]
cart: ICart
orders: IOrderCart[]
catprods: ICatProd[]
productInfos: IProductInfo[]
}
export interface IProducer {
@@ -110,6 +110,12 @@ export interface ICategory {
img?: string,
}
export interface ICatProd {
_id?: any
name: string,
img?: string,
}
export interface IStorehouse {
_id?: any
idapp?: string

View File

View File

@@ -0,0 +1,24 @@
import { defineComponent } from 'vue'
import { CImgText } from '../../../components/CImgText/index'
import { CCard } from '@/components/CCard'
import { CMyPage } from '@/components/CMyPage'
import { CTitleBanner } from '@/components/CTitleBanner'
import { CGridTableRec } from '@/components/CGridTableRec'
import { colTableCatProd } from '@src/store/Modules/fieldsTable'
import MixinMetaTags from '@/mixins/mixin-metatags'
export default defineComponent({
name: 'CatProdPage',
components: { CImgText, CCard, CMyPage, CTitleBanner, CGridTableRec },
setup() {
const { setmeta } = MixinMetaTags()
return {
colTableCatProd,
setmeta,
}
}
})

View File

@@ -0,0 +1,31 @@
<template>
<CMyPage title="Categorie" imgbackground="images/produttori.jpg" sizes="max-height: 120px">
<span>{{
setmeta({
title: 'Categorie',
description: '',
keywords: '',
})
}}
</span>
<div class="q-ma-sm q-gutter-sm q-pa-xs">
<CTitleBanner title="Categorie"></CTitleBanner>
<CGridTableRec
prop_mytable="catprods"
prop_mytitle="Categorie"
:prop_mycolumns="colTableCatProd"
prop_colkey="name"
nodataLabel="Nessuna Categoria"
noresultLabel="Il filtro selezionato non ha trovato nessun risultato">
</CGridTableRec>
</div>
</CMyPage>
</template>
<script lang="ts" src="./catprods.ts">
</script>
<style lang="scss" scoped>
@import 'catprods.scss';
</style>

View File

@@ -0,0 +1,24 @@
import { defineComponent } from 'vue'
import { CImgText } from '../../../components/CImgText/index'
import { CCard } from '@/components/CCard'
import { CMyPage } from '@/components/CMyPage'
import { CTitleBanner } from '@/components/CTitleBanner'
import { CGridTableRec } from '@/components/CGridTableRec'
import { colTableProductInfos } from '@src/store/Modules/fieldsTable'
import MixinMetaTags from '@/mixins/mixin-metatags'
export default defineComponent({
name: 'ProductInfosPage',
components: { CImgText, CCard, CMyPage, CTitleBanner, CGridTableRec },
setup() {
const { setmeta } = MixinMetaTags()
return {
colTableProductInfos,
setmeta,
}
}
})

View File

@@ -0,0 +1,32 @@
<template>
<CMyPage title="Info Prodotti" imgbackground="images/prodotti.jpg" sizes="max-height: 120px">
<span>{{
setmeta({
title: 'Info Prodotti',
description: '',
keywords: '',
})
}}
</span>
<div class="q-ma-sm q-gutter-sm q-pa-xs">
<CTitleBanner title="Info Prodotti"></CTitleBanner>
<CGridTableRec
prop_mytable="productinfos"
prop_mytitle="Lista Info Prodotti"
:prop_mycolumns="colTableProductInfos"
prop_colkey="name"
nodataLabel="Nessun Info Prodotto"
noresultLabel="Il filtro selezionato non ha trovato nessun risultato">
</CGridTableRec>
</div>
</CMyPage>
</template>
<script lang="ts" src="./productInfos.ts">
</script>
<style lang="scss" scoped>
@import 'productInfos.scss';
</style>

View File

@@ -69,6 +69,20 @@ function getRoutesEcomm(site: ISites) {
onlyManager: true,
onlyEditor: true
},
{
active: true,
order: 30,
path: '/admin/ecommerce/productInfos',
materialIcon: 'fas fa-lemon',
name: 'pages.productInfos',
component: () => import('@/rootgen/admin/productInfos/productInfos.vue'),
inmenu: true,
submenu: true,
level_parent: 0,
level_child: 0.5,
onlyManager: true,
onlyEditor: true
},
{
active: true,
order: 30,
@@ -184,10 +198,10 @@ function getRoutesEcomm(site: ISites) {
{
active: true,
order: 32,
path: '/admin/ecommerce/categories',
path: '/admin/ecommerce/catprods',
materialIcon: 'fas fa-file-alt',
name: 'pages.categories',
component: () => import('@/rootgen/admin/categories/categories.vue'),
name: 'pages.catprods',
component: () => import('@/rootgen/admin/catprods/catprods.vue'),
inmenu: true,
submenu: true,
level_parent: 0,
@@ -208,6 +222,15 @@ function getRoutesEcomm(site: ISites) {
inmenu: false,
infooter: false,
},
{
active: true,
order: 30,
path: '/admin/ecommerce/productInfos',
name: 'pages.productInfos',
component: () => import('@src/rootgen/admin/productInfos/productInfos.vue'),
inmenu: false,
infooter: false,
},
{
active: true,
order: 31,
@@ -302,7 +325,7 @@ function getRoutesEcomm(site: ISites) {
{
active: true,
order: 1000,
path: '/product/:codprod',
path: '/product/:idprod/:cosa',
materialIcon: 'event',
name: 'otherpages.product',
component: () => import('@/views/ecommerce/productInfo/productInfo.vue'),

View File

@@ -63,6 +63,7 @@ const msg_it = {
quantityAvailable: 'Disponibili',
stockQty: 'In Magazzino',
minBuyQty: 'Qta minima acquistabile',
maxBookableQty: 'Qtà massima prenotabile singolarm.',
bookableQty: 'Prenotabili',
bookableAvailableQty: 'Disponib. Prenotabili',
weight: 'Peso',
@@ -83,7 +84,8 @@ const msg_it = {
price_acquistato: 'Prezzo Acquistato',
vegan: 'Vegano',
gasordine: 'Ordine Gas',
select_gasordine: 'Scegli l\'Ordine del GAS'
select_gasordine: 'Scegli l\'Ordine del GAS',
productInfo: 'Info Prodotto',
},
storehouses: {
name: 'Magazzino',
@@ -1677,6 +1679,7 @@ const msg_it = {
code_o_text_search: 'Inserisci il codice o il testo da cercare',
code_add_to_cart: 'Aggiungi un codice al carrello',
qta_prenotate_in_attesa: '(Preordinate In attesa {qty})',
prodotti_trovati: '{qta} Prodotti trovati su {qtatot}',
},
gas: {
name: 'Ordine Gas',

View File

@@ -417,6 +417,13 @@ export const colTablecategories = [
AddCol(DuplicateRec),
]
export const colTableCatProd = [
AddCol({ name: 'name', label_trans: 'categories.name' }),
AddCol({ name: 'img', label_trans: 'categories.img' }),
AddCol(DeleteRec),
AddCol(DuplicateRec),
]
export const colTableStorehouse = [
AddCol({ name: 'name', label_trans: 'store.name' }),
AddCol({ name: 'description', label_trans: 'store.description' }),
@@ -1955,8 +1962,7 @@ export const colTableIscrittiArcadei = [
AddCol(DuplicateRec),
]
export const colTableProducts = [
AddCol({ name: 'active', label_trans: 'products.active', fieldtype: costanti.FieldType.boolean }),
export const colTableProductInfos = [
AddCol({ name: 'code', label_trans: 'products.code', required: true }),
AddCol({ name: 'codice_EAN', label_trans: 'products.codice_EAN' }),
AddCol({ name: 'barcode', label_trans: 'products.barcode' }),
@@ -1964,7 +1970,41 @@ export const colTableProducts = [
AddCol({ name: 'description', label_trans: 'products.description', fieldtype: costanti.FieldType.html }),
AddCol({ name: 'icon', label_trans: 'products.icon' }),
AddCol({ name: 'img', label_trans: 'products.img' }),
// AddCol({ name: 'idProducer', label_trans: 'products.idProducer' }),
AddCol({
name: 'department',
label_trans: 'products.department',
fieldtype: costanti.FieldType.select,
jointable: 'departments',
}),
AddCol({
name: 'idCatProds',
label_trans: 'products.category',
fieldtype: costanti.FieldType.multiselect,
jointable: 'catprods',
}),
AddCol({ name: 'color', label_trans: 'products.color' }),
AddCol({ name: 'size', label_trans: 'products.size' }),
AddCol({ name: 'weight', label_trans: 'products.weight', fieldtype: costanti.FieldType.number }),
AddCol({ name: 'vegan', label_trans: 'products.vegan', fieldtype: costanti.FieldType.boolean }),
AddCol({ name: 'unit', label_trans: 'products.unit',
fieldtype: costanti.FieldType.select, jointable: 'units', }),
AddCol({ name: 'stars', label_trans: 'products.stars', fieldtype: costanti.FieldType.number }),
AddCol({ name: 'date', label_trans: 'products.date', fieldtype: costanti.FieldType.date }),
AddCol({ name: 'ingredienti', label_trans: 'products.ingredienti' }),
AddCol({ name: 'valori_nutrizionali', label_trans: 'products.valori_nutrizionali' }),
AddCol({ name: 'note', label_trans: 'products.note' }),
AddCol(DeleteRec),
AddCol(DuplicateRec),
]
export const colTableProducts = [
AddCol({ name: 'active', label_trans: 'products.active', fieldtype: costanti.FieldType.boolean }),
AddCol({
name: 'idProductInfo',
label_trans: 'products.productInfo',
fieldtype: costanti.FieldType.select,
jointable: 'productinfos',
}),
AddCol({
name: 'idProducer',
label_trans: 'products.producer',
@@ -1995,39 +2035,19 @@ export const colTableProducts = [
fieldtype: costanti.FieldType.multiselect,
jointable: 'scontisticas',
}),
AddCol({
name: 'department',
label_trans: 'products.department',
fieldtype: costanti.FieldType.select,
jointable: 'departments',
}),
// AddCol({ name: 'department', label_trans: 'products.department' }),
AddCol({
name: 'category',
label_trans: 'products.category',
fieldtype: costanti.FieldType.multiselect,
jointable: 'categorys',
}),
AddCol({ name: 'price', label_trans: 'products.price', fieldtype: costanti.FieldType.number, required: true }),
AddCol({ name: 'price_acquistato', label_trans: 'products.price_acquistato', fieldtype: costanti.FieldType.number, required: true }),
AddCol({ name: 'after_price', label_trans: 'products.after_price' }),
AddCol({ name: 'color', label_trans: 'products.color' }),
AddCol({ name: 'size', label_trans: 'products.size' }),
/*AddCol({
name: 'quantityAvailable',
label_trans: 'products.quantityAvailable',
fieldtype: costanti.FieldType.number
}),
AddCol({
name: 'bookableAvailableQty',
label_trans: 'products.bookableAvailableQty',
fieldtype: costanti.FieldType.number
}), */
AddCol({
name: 'minBuyQty',
label_trans: 'products.minBuyQty',
fieldtype: costanti.FieldType.number
}),
AddCol({
name: 'maxBookableQty',
label_trans: 'products.maxBookableQty',
fieldtype: costanti.FieldType.number
}),
AddCol({
name: 'stockQty',
label_trans: 'products.stockQty',
@@ -2040,15 +2060,6 @@ export const colTableProducts = [
}),
AddCol({ name: 'canBeShipped', label_trans: 'products.canBeShipped', fieldtype: costanti.FieldType.boolean }),
AddCol({ name: 'canBeBuyOnline', label_trans: 'products.canBeBuyOnline', fieldtype: costanti.FieldType.boolean }),
AddCol({ name: 'weight', label_trans: 'products.weight', fieldtype: costanti.FieldType.number }),
AddCol({ name: 'vegan', label_trans: 'products.vegan', fieldtype: costanti.FieldType.boolean }),
AddCol({ name: 'unit', label_trans: 'products.unit',
fieldtype: costanti.FieldType.select, jointable: 'units', }),
AddCol({ name: 'stars', label_trans: 'products.stars', fieldtype: costanti.FieldType.number }),
AddCol({ name: 'date', label_trans: 'products.date', fieldtype: costanti.FieldType.date }),
AddCol({ name: 'ingredienti', label_trans: 'products.ingredienti' }),
AddCol({ name: 'valori_nutrizionali', label_trans: 'products.valori_nutrizionali' }),
AddCol({ name: 'note', label_trans: 'products.note' }),
AddCol(DeleteRec),
AddCol(DuplicateRec),
]
@@ -3560,7 +3571,14 @@ export const fieldsTable = {
label: 'Prodotti',
columns: colTableProducts,
colkey: '_id',
collabel: 'name',
collabel: '_id',
},
{
value: 'productinfos',
label: 'Info Prodotti',
columns: colTableProductInfos,
colkey: '_id',
collabel: (rec: any) => `${rec.name} (${rec.code})`,
},
{
value: 'producers',
@@ -3597,6 +3615,13 @@ export const fieldsTable = {
colkey: '_id',
collabel: 'name',
},
{
value: 'catprods',
label: 'Categorie',
columns: colTableCatProd,
colkey: '_id',
collabel: 'name',
},
{
value: 'gasordines',
label: 'Gas Ordini',

View File

@@ -8253,7 +8253,7 @@ export const tools = {
},
getWeightTotalByOrder(order: IOrder) {
return (order.product && order.product.weight ? order.product.weight : 1) * (order.quantitypreordered | 0 + order.quantity | 0)
return (order.product && order.product.productInfo && order.product.productInfo.weight ? order.product.productInfo.weight : 1) * (order.quantitypreordered | 0 + order.quantity | 0)
},
isPartecipero(myrec: any) {
@@ -8275,7 +8275,13 @@ export const tools = {
return inputString.replace('\\', '').replace(/"/g, '')
},
isObjectEmpty(obj: any) {
return Object.keys(obj).length === 0;
},
strToVal(mystr: string) {
return parseInt(mystr)
}
// FINE !

View File

@@ -1,4 +1,4 @@
import { IBaseOrder, ICart, IOrder, IOrderCart, IProduct, IProductsState } from 'model'
import { IBaseOrder, ICart, IOrder, IOrderCart, IProduct, IProductsState, IProductInfo, ICatProd } from 'model'
import { Api } from '@api'
import { serv_constants } from '@src/store/Modules/serv_constants'
@@ -14,25 +14,69 @@ import { ref } from 'vue'
import translate from '@src/globalroutines/util'
function getRecordProductInfoEmpty(): IProductInfo {
return {
code: '',
name: '',
description: '',
department: '',
catprods: [],
color: '',
size: '',
weight: 0,
unit: 0,
stars: 0,
date: tools.getDateNow(),
icon: '',
img: '',
}
}
function getRecordProductEmpty() {
return {
active: false,
productInfo: {
img: '', code: '', name: '',
},
storehouses: [], scontisticas: [],
price: 0, stockQty: 0, bookableQty: 0, gasordines: [],
idGasordines: [], minBuyQty: 1, maxBookableQty: 0,
}
}
export const useProducts = defineStore('Products', {
state: (): IProductsState => ({
products: [],
cart: { items: [], totalPrice: 0, totalQty: 0, userId: '' },
orders: [],
catprods: [],
productInfos: [],
}),
getters: {
getCatProds: (state: IProductsState) => (): ICatProd[] => {
return state.catprods
},
getNumProdTot: (state: IProductsState) => (): number => {
return state.products.length
},
getProducts: (state: IProductsState) => (cosa?: number): IProduct[] => {
if (!!cosa) {
let ris = null
if (cosa === shared_consts.PROD.GAS) {
ris = state.products.filter((rec) => (rec.idGasordines && rec.idGasordines.length > 0))
} else if (cosa === shared_consts.PROD.BOTTEGA) {
ris = state.products.filter((rec) => (!rec.idGasordines || (rec.idGasordines && rec.idGasordines.length === 0)))
}
return ris ? ris : []
return state.products.filter((rec: IProduct) => {
const hasGasOrdines = rec.idGasordines && rec.idGasordines.length > 0;
if ((cosa === shared_consts.PROD.GAS && hasGasOrdines) ||
(cosa === shared_consts.PROD.BOTTEGA && ((!hasGasOrdines || (hasGasOrdines && rec.idGasordines?.length === 0))))) {
return true;
}
return false;
});
} else {
return state.products
return state.products;
}
},
@@ -65,18 +109,24 @@ export const useProducts = defineStore('Products', {
},
getProductById: (state: IProductsState) => (id: string): IProduct => {
const prod = state.products.find((prod: IProduct) => prod._id === id)
return prod ? prod : { active: false, img: '', code: '', name: '', storehouses: [], scontisticas: [], price: 0, stockQty: 0, bookableQty: 0, gasordines: [], idGasordines: [], minBuyQty: 1 }
return prod ? prod : getRecordProductEmpty()
},
getProductByCode: (state: IProductsState) => (code: string): IProduct => {
const prod = state.products.find((prod: IProduct) => prod.code === code)
return prod ? prod : {
active: false, img: '', code: '', name: '', storehouses: [], scontisticas: [], price: 0,
gasordines: [], idGasordines: [],
stockQty: 0, bookableQty: 0, minBuyQty: 1
if (!code) {
return getRecordProductEmpty()
}
const prod = state.products.find((prod: IProduct) => {
if (prod.productInfo.code === code)
return prod
else
return null
})
return prod ? prod : getRecordProductEmpty()
},
getCart: (state: IProductsState) => (): ICart => {
@@ -218,12 +268,14 @@ export const useProducts = defineStore('Products', {
return []
},
getRecordEmpty: (state: IProductsState) => (): IProduct => {
const tomorrow = tools.getDateNow()
tomorrow.setDate(tomorrow.getDate() + 1)
return {
productInfo: getRecordProductInfoEmpty(),
// _id: tools.getDateNow().toISOString(), // Create NEW
active: false,
idProducer: '',
@@ -236,63 +288,40 @@ export const useProducts = defineStore('Products', {
producer: {},
storehouses: [],
provider: {},
code: '',
name: '',
description: '',
department: '',
category: '',
price: 0.0,
color: '',
size: '',
quantityAvailable: 0,
bookableAvailableQty: 0,
stockQty: 0,
minBuyQty: 1,
maxBookableQty: 0,
bookableQty: 0,
canBeShipped: false,
QuantitaOrdinateInAttesa: 0,
QuantitaPrenotateInAttesa: 0,
canBeBuyOnline: false,
weight: 0,
unit: 0,
stars: 0,
date: tools.getDateNow(),
icon: '',
img: '',
}
},
},
actions: {
getProductsByCategory(category: string): any[] {
return this.products.filter((rec) => rec.category === category)
},
createOrderByProduct(product: IProduct, order: IOrder): IOrder {
const userStore = useUserStore()
const myorder: IOrder = {
userId: userStore.my._id,
idapp: process.env.APP_ID,
idProduct: product._id,
idProducer: product.idProducer,
status: shared_consts.OrderStatus.IN_CART,
TotalPriceProduct: 0,
idProduct: product._id,
product, // Copia tutto l'oggetto Product !
// Ordine:
price: product.price,
after_price: product.after_price,
color: product.color,
size: product.size,
weight: product.weight,
quantity: order.quantity,
quantitypreordered: order.quantitypreordered,
idStorehouse: order.idStorehouse,
idGasordine: order.idGasordine,
idScontisticas: product.idScontisticas,
}
if (product.storehouses.length === 1) {
myorder.idStorehouse = product.storehouses[0]._id
idStorehouse: order.idStorehouse,
}
return myorder
@@ -306,6 +335,12 @@ export const useProducts = defineStore('Products', {
},
/*resetProducts() {
const arrprod = [...this.products]
this.products = []
this.products = [...arrprod]
},*/
async loadProducts() {
const userStore = useUserStore()
@@ -484,11 +519,11 @@ export const useProducts = defineStore('Products', {
}
} else {
if (this.isQtyAvailableByProduct(product)) {
order.quantity = 1
order.quantity = product.minBuyQty | 1
order.quantitypreordered = 0
} else {
if (this.isInPreorderByProduct(product)) {
order.quantitypreordered = 1
order.quantitypreordered = product.minBuyQty | 1
order.quantity = 0
}
}
@@ -650,8 +685,8 @@ export const useProducts = defineStore('Products', {
return ris
},
async addtoCartBase({ $q, t, code, order, addqty }: { $q: any, t: any, code: string, order: IOrder, addqty: boolean }) {
let product = this.getProductByCode(code)
async addtoCartBase({ $q, t, id, order, addqty }: { $q: any, t: any, id: string, order: IOrder, addqty: boolean }) {
let product = this.getProductById(id)
return await this.addToCart({ product, order, addqty })
.then((ris) => {

View File

@@ -122,6 +122,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
storehouses: [],
scontisticas: [],
providers: [],
catprods: [],
gasordines: [],
departments: [],
categories: [],
@@ -282,6 +283,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
let ris: any = []
const calendarStore = useCalendarStore()
const Products = useProducts()
const circuitStore = useCircuitStore()
const userStore = useUserStore()
const messageStore = useMessageStore()
@@ -310,6 +312,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
else if (table === 'producers') ris = state.producers
else if (table === 'storehouses') ris = state.storehouses
else if (table === 'providers') ris = state.providers
else if (table === 'productinfos') ris = Products.productInfos
else if (table === 'gasordines') ris = state.gasordines
else if (table === 'scontisticas') ris = state.scontisticas
else if (table === 'groups') ris = state.groups
@@ -317,6 +320,7 @@ export const useGlobalStore = defineStore('GlobalStore', {
else if (table === 'workers') ris = state.workers
else if (table === 'departments') ris = state.departments
else if (table === 'categorys') ris = state.categories
else if (table === 'catprods') ris = Products.catprods
else if (table === 'sharewithus') ris = state.sharewithus
else if (table === 'paymenttypes') ris = state.paymenttypes
else if (table === 'circuits') ris = circuitStore.listcircuits
@@ -1536,9 +1540,13 @@ export const useGlobalStore = defineStore('GlobalStore', {
this.paymenttypes = (res.data.paymenttypes) ? [...res.data.paymenttypes] : []
this.gallery = (res.data.gallery) ? [...res.data.gallery] : []
this.calzoom = (res.data.calzoom) ? [...res.data.calzoom] : []
Products.productInfos = (res.data.productInfos) ? [...res.data.productInfos] : []
this.producers = (res.data.producers) ? [...res.data.producers] : []
this.storehouses = (res.data.storehouses) ? [...res.data.storehouses] : []
this.providers = (res.data.providers) ? [...res.data.providers] : []
Products.catprods = (res.data.catprods) ? [...res.data.catprods] : []
this.gasordines = (res.data.gasordines) ? [...res.data.gasordines] : []
this.scontisticas = (res.data.scontisticas) ? [...res.data.scontisticas] : []
this.groups = (res.data.groups) ? [...res.data.groups] : []

View File

@@ -253,6 +253,31 @@
></q-btn>
<br />
</div>
<div class="row">
<q-btn
label="10. Elimina la Tabella PRODUCTS e PRODUCTINFOS !)"
color="negative"
@click="EseguiFunz('dropProducts')"
></q-btn>
<br />
</div>
<div class="row">
<q-btn
label="11. Elimina tutti gli ORDINI ! (Orders, Orderscart, Cart) !)"
color="negative"
@click="EseguiFunz('dropAllOrders')"
></q-btn>
<br />
</div>
<div class="row">
<q-btn
label="12. Elimina tutti i Carrelli (Cart) !)"
color="negative"
@click="EseguiFunz('dropAllCarts')"
></q-btn>
<br />
</div>
<div class="row">
<q-btn

View File

@@ -4,7 +4,7 @@
<div class="container">
<div class="row">
<div class="q-pa-md row items-start q-gutter-md" v-for="(product, index) in getProducts()" :key="index">
<CProductCard :code="product.code"/>
<CProductCard :id="product._id"/>
</div>
</div>
</div>

View File

@@ -8,7 +8,7 @@ import { useI18n } from '@/boot/i18n'
import { toolsext } from '@store/Modules/toolsext'
import { useQuasar } from 'quasar'
import { costanti } from '@costanti'
import { ICart, IOrder, IOrderCart, IShareWithUs } from '@src/model/Products'
import { ICart, IOrder, IOrderCart, IProduct, IShareWithUs } from '@src/model/Products'
import { shared_consts } from '@src/common/shared_vuejs'
@@ -178,13 +178,39 @@ export default defineComponent({
})
}
function getActualIdStorehouse(myprod: IProduct) {
// Ottieni il negozio attualmente selezionato:
// Se ce n'è solo 1 allora prendi quello !
if (myprod.storehouses.length === 1) {
return myprod.storehouses[0]._id
} else {
// Ottieni il negozio attualmente scelto !
return ''
}
}
function getActualGasordine(myprod: IProduct) {
// Ottieni il negozio attualmente selezionato:
// Se ce n'è solo 1 allora prendi quello !
if (myprod.gasordines.length === 1) {
return myprod.gasordines[0]._id
} else {
// Ottieni il gasordine attualmente scelto !
return ''
}
}
async function insertArticolo() {
let lowerSearchText = search.value.trim();
const myprod = productStore.getProductByCode(lowerSearchText);
if (myprod && myprod.active) {
let myorder: IOrder = { quantity: 1, quantitypreordered: 0, price: 0, TotalPriceProduct: 0 }
await productStore.addtoCartBase({ $q, t, code: myprod.code!, order: myorder, addqty: true })
let myorder: IOrder = { quantity: 1, quantitypreordered: 0,
TotalPriceProduct: 0, price: 0,
idStorehouse: getActualIdStorehouse(myprod),
idGasordine: getActualGasordine(myprod),
}
await productStore.addtoCartBase({ $q, t, id: myprod._id, order: myorder, addqty: true })
search.value = ''
load()
}

View File

@@ -25,7 +25,7 @@ export default defineComponent({
const productStore = useProducts()
const $router = useRouter()
const $q = useQuasar()
const { t } = useI18n();
const { t } = useI18n()
const myorderscart = ref(<IOrderCart[] | undefined>[])
const myarrrec = ref(<any>{})
@@ -313,6 +313,7 @@ export default defineComponent({
endload,
getOrdersCartWithTotals,
productStore,
t,
}
}
})

View File

@@ -54,10 +54,10 @@
:key="index"
>
<div
v-if="!!item && item.order && item.order.product"
v-if="!!item && item.order && item.order.product && item.order.product.productInfo"
>
{{ item.order.product.name }} ({{
productStore.getQuantityByOrder($t, item.order)
{{ item.order.product.productInfo.name }} ({{
productStore.getQuantityByOrder(t, item.order)
}})<br />
</div>
</div>
@@ -139,8 +139,8 @@
</q-td>
<q-td key="items" :props="props">
<div v-for="(item, index) of props.row.items" :key="index">
<div v-if="!!item.order && item.order.product">
{{ item.order.product.name }} ({{
<div v-if="!!item.order && item.order.product && item.order.product.productInfo">
{{ item.order.product.productInfo.name }} ({{
productStore.getQuantityByOrder($t, item.order)
}})<br />
</div>

View File

@@ -15,7 +15,7 @@ import { CProductCard } from '@src/components/CProductCard'
export default defineComponent({
name: 'ProductInfo',
name: 'productInfo',
components: { CProductCard },
props: {},
setup() {
@@ -26,7 +26,8 @@ export default defineComponent({
const $route = useRoute()
const $q = useQuasar()
const { t } = useI18n();
const code = ref('')
const id = ref('')
const cosa = ref(0)
// const { setValDb, getValDb } = MixinBase()
@@ -34,11 +35,13 @@ export default defineComponent({
// Inizializza
console.log('created productInfo')
console.log($route)
if (!!$route.params.codprod) {
code.value = $route.params.codprod.toString()
if (!!$route.params.idprod) {
id.value = $route.params.idprod.toString()
}
if (!!$route.params.idprod) {
cosa.value = tools.strToVal($route.params.cosa.toString())
}
console.log('code', code)
}
onMounted(mounted)
@@ -49,7 +52,8 @@ export default defineComponent({
tools,
toolsext,
shared_consts,
code,
id,
cosa,
}
}
})

View File

@@ -3,7 +3,7 @@
<div class="panel">
<div class="container">
<div class="row">
<CProductCard :code="code" complete="true"/>
<CProductCard :id="id" :cosa="cosa" :complete="true"/>
</div>
</div>
</div>

View File

@@ -3,3 +3,12 @@ $heightBtn: 100%;
.card .product-image {
height: 300px;
}
.container{
margin-top: 4px;
margin-bottom: 4px;
}
.prod_trov{
font-style: italic;
}

View File

@@ -1,4 +1,4 @@
import { defineComponent, onMounted, ref, watch } from 'vue'
import { defineComponent, onMounted, ref, watch, computed } from 'vue'
import { tools } from '@store/Modules/tools'
import { useUserStore } from '@store/UserStore'
import { useRouter } from 'vue-router'
@@ -29,40 +29,71 @@ export default defineComponent({
const search = ref('')
const cosa = ref(0)
const cat = ref('')
watch(() => cosa.value, (newval, oldval) => {
tools.setCookie(tools.COOK_COSA_PRODOTTI, cosa.value.toString())
})
function mounted() {
cosa.value = tools.getCookie(tools.COOK_COSA_PRODOTTI, shared_consts.PROD.BOTTEGA, true)
// Inizializza
productStore.loadProducts()
}
function getProducts() {
const getArrProducts = computed(() => {
let arrprod = productStore.getProducts(cosa.value)
if (!search.value) {
let catstr = cat.value;
if (!search.value && !catstr) {
return arrprod
}
let lowerSearchText = search.value.toLowerCase();
return arrprod.filter((product: IProduct) => {
let lowerName = product.name!.toLowerCase();
return product.code!.includes(search.value) || lowerName.includes(lowerSearchText);
});
let lowerName = product.productInfo.name!.toLowerCase()
let hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr))
return (product.productInfo.code!.includes(search.value) || lowerName.includes(lowerSearchText)) && hasCategoria
});
})
/*function getProducts() {
let arrprod = productStore.getProducts(cosa.value)
if (!search.value) {
return arrprod
}
let lowerSearchText = search.value.toLowerCase();
let catstr = cat.value;
return arrprod.filter((product: IProduct) => {
let lowerName = product.productInfo.name!.toLowerCase();
const hasCategoria = !catstr || (catstr && product.productInfo.idCatProds?.includes(catstr));
return (product.productInfo.code!.includes(search.value) || lowerName.includes(lowerSearchText)) && hasCategoria
});
}*/
function mounted() {
cosa.value = tools.getCookie(tools.COOK_COSA_PRODOTTI, shared_consts.PROD.BOTTEGA, true)
// Inizializza
productStore.loadProducts()
}
function getCatProds() {
let arrcat = productStore.getCatProds()
let riscat = [{ label: 'Tutti', value: '' }]
for (const rec of arrcat) {
riscat.push({ label: rec.name, value: rec._id })
}
return riscat
}
function getNumQtaGas() {
const arrprod = productStore.getProducts(shared_consts.PROD.GAS)
return arrprod.length
}
function getNumQtaBottega() {
const arrprod = productStore.getProducts(shared_consts.PROD.BOTTEGA)
return arrprod.length
}
onMounted(mounted)
return {
@@ -70,12 +101,16 @@ export default defineComponent({
costanti,
tools,
toolsext,
getProducts,
getArrProducts,
search,
cosa,
shared_consts,
getNumQtaGas,
getNumQtaBottega,
getCatProds,
cat,
productStore,
t,
}
}
})

View File

@@ -18,9 +18,9 @@
<template v-slot:gas>
<div class="row items-center no-wrap">
<div class="text-center">
{{ $t('gas.ordina_sul_gas') }}
{{ t('gas.ordina_sul_gas') }}
<br />
{{ $t('gas.x_prodotti_gas', { qta: getNumQtaGas() }) }}
{{ t('gas.x_prodotti_gas', { qta: getNumQtaGas() }) }}
</div>
<q-icon right name="fas fa-user-friends" />
</div>
@@ -29,10 +29,10 @@
<template v-slot:bottega>
<div class="row items-center no-wrap">
<div class="text-center">
{{ $t('gas.bottega') }}
{{ t('gas.bottega') }}
<br />
{{
$t('gas.x_prodotti_bottega', { qta: getNumQtaBottega() })
t('gas.x_prodotti_bottega', { qta: getNumQtaBottega() })
}}
</div>
<q-icon right name="fas fa-store" />
@@ -43,13 +43,13 @@
</div>
<div class="container">
<div
class="q-gutter-y-md column text-center q-mx-auto"
class="q-gutter-y-md column text-center q-mx-auto q-py-sm"
style="width: 350px; max-width: 100%"
>
<q-input
filledd
stack-label
:label="$t('ecomm.code_o_text_search')"
:label="t('ecomm.code_o_text_search')"
v-model="search"
class="q-ml-md"
>
@@ -58,13 +58,35 @@
</template>
</q-input>
</div>
<div class="row q-gutter-sm justify-evenly q-mx-auto">
<div v-for="(reccat, index) in getCatProds()" :key="index">
<q-btn
:push="cat === reccat.value"
dense
rounded
:color="cat === reccat.value ? 'blue' : undefined"
glossy
:label="reccat.label"
@click="cat = reccat.value"
>
</q-btn>
</div>
</div>
<div class="text-center q-py-sm prod_trov">
{{
t('ecomm.prodotti_trovati', {
qta: getArrProducts.length,
qtatot: productStore.getNumProdTot(),
})
}}{{}}
</div>
<div class="row">
<div
class="q-pa-md row items-start q-gutter-md"
v-for="(product, index) in getProducts()"
v-for="(product, index) in getArrProducts"
:key="index"
>
<CProductCard :code="product.code" :complete="false" :cosa="cosa" />
<CProductCard :id="product._id" :complete="false" :cosa="cosa" />
</div>
</div>
</div>