fix conflict

This commit is contained in:
Mohit Panjwani
2019-11-12 18:41:25 +05:30
40 changed files with 2102 additions and 377 deletions

View File

@ -79,7 +79,7 @@ class ItemsController extends Controller
foreach ($request->taxes as $tax) { foreach ($request->taxes as $tax) {
$item->taxes()->updateOrCreate( $item->taxes()->updateOrCreate(
['tax_type_id' => $tax['tax_type_id']], ['tax_type_id' => $tax['tax_type_id']],
['amount' => $tax['amount'], 'percent' => $tax['percent'], 'percent' => $tax['name']] ['amount' => $tax['amount'], 'percent' => $tax['percent'], 'name' => $tax['name']]
); );
} }
} }

View File

@ -18173,6 +18173,7 @@ fieldset[disabled] .multiselect {
.reports .report-view-button { .reports .report-view-button {
display: none; display: none;
color: #fff;
} }
.reports .report-fields-container { .reports .report-fields-container {
@ -18208,8 +18209,13 @@ fieldset[disabled] .multiselect {
display: none; display: none;
} }
.reports .report-submit-button-container {
display: none;
}
.reports .report-view-button { .reports .report-view-button {
display: flex; display: flex;
color: #fff !important;
justify-content: center; justify-content: center;
} }

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -35,6 +35,8 @@
<div v-if="$v.formData.price.$error"> <div v-if="$v.formData.price.$error">
<span v-if="!$v.formData.price.required" class="text-danger">{{ $tc('validation.required') }}</span> <span v-if="!$v.formData.price.required" class="text-danger">{{ $tc('validation.required') }}</span>
<span v-if="!$v.formData.price.numeric" class="text-danger">{{ $tc('validation.numbers_only') }}</span> <span v-if="!$v.formData.price.numeric" class="text-danger">{{ $tc('validation.numbers_only') }}</span>
<span v-if="!$v.formData.price.maxLength" class="text-danger">{{ $t('validation.price_maxlength') }}</span>
<span v-if="!$v.formData.price.minValue" class="text-danger">{{ $t('validation.price_minvalue') }}</span>
</div> </div>
</div> </div>
</div> </div>
@ -138,7 +140,8 @@ export default {
price: { price: {
required, required,
numeric, numeric,
minValue: minValue(0.1) minValue: minValue(0.1),
maxLength: maxLength(10)
}, },
description: { description: {
maxLength: maxLength(255) maxLength: maxLength(255)

View File

@ -9,6 +9,7 @@
<script> <script>
import Chart from 'chart.js' import Chart from 'chart.js'
import Utils from '../../helpers/utilities' import Utils from '../../helpers/utilities'
import { mapGetters } from 'vuex'
export default { export default {
props: { props: {
@ -46,9 +47,20 @@ export default {
type: Function, type: Function,
require: false, require: false,
default: Function default: Function
},
FormatGraphMoney: {
type: Function,
require: false,
default: Function
} }
}, },
computed: {
...mapGetters('currency', [
'defaultCurrency'
])
},
watch: { watch: {
labels (val) { labels (val) {
this.update() this.update()
@ -56,6 +68,7 @@ export default {
}, },
mounted () { mounted () {
let self = this
let context = this.$refs.graph.getContext('2d') let context = this.$refs.graph.getContext('2d')
let options = { let options = {
responsive: true, responsive: true,
@ -64,7 +77,7 @@ export default {
enabled: true, enabled: true,
callbacks: { callbacks: {
label: function (tooltipItem, data) { label: function (tooltipItem, data) {
return Utils.formatGraphMoney(tooltipItem.value) return self.FormatGraphMoney(tooltipItem.value, self.defaultCurrency)
} }
} }
}, },

View File

@ -549,6 +549,16 @@ export default {
action: 'Action', action: 'Action',
add_currency: 'Add Currency' add_currency: 'Add Currency'
}, },
mail: {
host: 'Mail Host',
port: 'Mail Port',
driver: 'Mail Driver',
password: 'Mail Password',
username: 'Mail Username',
mail_config: 'Mail Configuration',
encryption: 'Mail Encryption',
mail_config_desc: 'Below details will be used to update the mail environment. Also you can change the details anytime after logging in.'
},
pdf: { pdf: {
title: 'PDF Setting', title: 'PDF Setting',
footer_text: 'Footer Text', footer_text: 'Footer Text',
@ -680,6 +690,7 @@ export default {
username: 'Username', username: 'Username',
next: 'Next', next: 'Next',
continue: 'Continue', continue: 'Continue',
skip: 'Skip',
database: { database: {
database: 'Site URL & Database', database: 'Site URL & Database',
connection: 'Database Connection', connection: 'Database Connection',
@ -750,7 +761,9 @@ export default {
payment_greater_than_due_amount: 'Entered Payment is more than due amount of this invoice.', payment_greater_than_due_amount: 'Entered Payment is more than due amount of this invoice.',
quantity_maxlength: 'Quantity should not be greater than 10 digits.', quantity_maxlength: 'Quantity should not be greater than 10 digits.',
price_maxlength: 'Price should not be greater than 10 digits.', price_maxlength: 'Price should not be greater than 10 digits.',
price_minvalue: 'Price should be greater than 0 digits',
amount_maxlength: 'Amount should not be greater than 10 digits.', amount_maxlength: 'Amount should not be greater than 10 digits.',
amount_minvalue: 'Amount should be greater than 0 digits',
description_maxlength: 'Description should not be greater than 255 characters.', description_maxlength: 'Description should not be greater than 255 characters.',
maximum_options_error: 'Maximum of {max} options selected. First remove a selected option to select another.', maximum_options_error: 'Maximum of {max} options selected. First remove a selected option to select another.',
notes_maxlength: 'Notes should not be greater than 255 characters.', notes_maxlength: 'Notes should not be greater than 255 characters.',

View File

@ -224,6 +224,7 @@ export default {
action: 'Acción', action: 'Acción',
notes: 'Notas', notes: 'Notas',
tax: 'Impuesto', tax: 'Impuesto',
send_estimate: 'Enviar presupuesto',
estimate_template: 'Plantilla de estimación', estimate_template: 'Plantilla de estimación',
convert_to_invoice: 'Convertir a factura', convert_to_invoice: 'Convertir a factura',
mark_as_sent: 'Marcar como enviado', mark_as_sent: 'Marcar como enviado',
@ -548,7 +549,7 @@ export default {
right: 'Derecho', right: 'Derecho',
left: 'Izquierda', left: 'Izquierda',
action: 'Acción', action: 'Acción',
add_currency: 'Agregar moneda', add_currency: 'Agregar moneda'
}, },
pdf: { pdf: {
title: 'Configuración de PDF', title: 'Configuración de PDF',
@ -595,8 +596,6 @@ export default {
estimate_viewed_desc: 'Cuando su cliente ve la estimación enviada a través del panel de control del cráter.', estimate_viewed_desc: 'Cuando su cliente ve la estimación enviada a través del panel de control del cráter.',
save: 'Salvar', save: 'Salvar',
email_save_message: 'Correo electrónico guardado con éxito', email_save_message: 'Correo electrónico guardado con éxito',
invoice_viewed_message: 'Factura vista',
estimate_viewed_message: 'Estimación vista',
please_enter_email: 'Por favor, introduzca su correo electrónico' please_enter_email: 'Por favor, introduzca su correo electrónico'
}, },
tax_types: { tax_types: {
@ -641,7 +640,6 @@ export default {
preference: 'Preferencia | Preferencias', preference: 'Preferencia | Preferencias',
general_settings: 'Preferencias predeterminadas para el sistema.', general_settings: 'Preferencias predeterminadas para el sistema.',
updated_message: 'Preferencias actualizadas exitosamente', updated_message: 'Preferencias actualizadas exitosamente',
set_discount_per_item_message: 'Descuento establecido por artículo',
select_language: 'seleccione el idioma', select_language: 'seleccione el idioma',
select_time_zone: 'selecciona la zona horaria', select_time_zone: 'selecciona la zona horaria',
select_date_formate: 'seleccione formato de fecha', select_date_formate: 'seleccione formato de fecha',
@ -675,7 +673,52 @@ export default {
language: 'Idioma', language: 'Idioma',
time_zone: 'Zona horaria', time_zone: 'Zona horaria',
fiscal_year: 'Año financiero', fiscal_year: 'Año financiero',
date_format: 'Formato de fecha' date_format: 'Formato de fecha',
from_address: 'De la Dirección',
username: 'Nombre de usuario',
next: 'Próximo',
continue: 'Hacer continuación',
database: {
database: 'URL del sitio y base de datose',
connection: 'Conexión de base de datos',
host: 'Database Host',
port: 'Host de base de datos',
password: 'Contraseña de base de datos',
app_url: 'URL de la aplicación',
username: 'Nombre de usuario de la base de datos',
db_name: 'Nombre de la base de datos',
desc: 'Cree una base de datos en su servidor y establezca las credenciales utilizando el siguiente formulario.'
},
permissions: {
permissions: 'Permisos',
permission_desc: 'A continuación se muestra la lista de permisos de carpeta necesarios para que la aplicación funcione. Si la verificación de permisos falla, asegúrese de actualizar los permisos de su carpeta.'
},
mail: {
host: 'Host de correo',
port: 'Puerto de correo',
driver: 'Conductor de correo',
password: 'Contraseña de correo',
username: 'Nombre de usuario de correo',
mail_config: 'Configuración de correo',
encryption: 'Cifrado de correo',
mail_config_desc: 'Los detalles a continuación se utilizarán para actualizar el entorno de correo. También puede cambiar los detalles en cualquier momento después de iniciar sesión.'
},
req: {
system_req: 'Requisitos del sistema',
php_req_version: 'Php (versión {version} necesario)',
check_req: 'Consultar requisitos',
system_req_desc: 'Crater tiene algunos requisitos de servidor. Asegúrese de que su servidor tenga la versión de php requerida y todas las extensiones mencionadas a continuación.'
},
errors: {
migrate_failed: 'La migración falló',
database_variables_save_error: 'No se puede conectar a la base de datos con los valores proporcionados.',
mail_variables_save_error: 'La configuración del correo electrónico ha fallado.',
connection_failed: 'Conexión de base de datos fallida'
},
success: {
mail_variables_save_successfully: 'Correo electrónico configurado correctamente',
database_variables_save_successfully: 'Base de datos configurada con éxito.'
}
}, },
layout_login: { layout_login: {
copyright_crater: 'Copyright @ Crater - 2019', copyright_crater: 'Copyright @ Crater - 2019',
@ -706,7 +749,9 @@ export default {
payment_greater_than_due_amount: 'El pago ingresado es mayor al monto adeudado de esta factura.', payment_greater_than_due_amount: 'El pago ingresado es mayor al monto adeudado de esta factura.',
quantity_maxlength: 'La cantidad no debe ser mayor de 10 dígitos.', quantity_maxlength: 'La cantidad no debe ser mayor de 10 dígitos.',
price_maxlength: 'El precio no debe ser mayor de 10 dígitos.', price_maxlength: 'El precio no debe ser mayor de 10 dígitos.',
price_minvalue: 'El precio debe ser mayor que 0 dígitos',
amount_maxlength: 'La cantidad no debe ser mayor de 10 dígitos.', amount_maxlength: 'La cantidad no debe ser mayor de 10 dígitos.',
amount_minvalue: 'La cantidad debe ser mayor que 0 dígitos',
description_maxlength: 'La descripción no debe tener más de 255 caracteres.', description_maxlength: 'La descripción no debe tener más de 255 caracteres.',
maximum_options_error: 'Máximo de {max} opciones seleccionadas. Primero elimine una opción seleccionada para seleccionar otra.', maximum_options_error: 'Máximo de {max} opciones seleccionadas. Primero elimine una opción seleccionada para seleccionar otra.',
notes_maxlength: 'Las notas no deben tener más de 255 caracteres.', notes_maxlength: 'Las notas no deben tener más de 255 caracteres.',

View File

@ -675,7 +675,52 @@ export default {
language: 'La langue', language: 'La langue',
time_zone: 'Fuseau horaire', time_zone: 'Fuseau horaire',
fiscal_year: 'Année financière', fiscal_year: 'Année financière',
date_format: 'Format de date' date_format: 'Format de date',
from_address: "De l'adresse",
username: "Nom d'utilisateur",
next: 'Suivant',
continue: 'Continuer',
database: {
database: 'URL du site et base de données',
connection: 'Connexion à la base de données',
host: 'Hôte de base de données',
port: 'Port de base de données',
password: 'Mot de passe de base de données',
app_url: 'Application URL',
username: "Nom d'utilisateur de la base de données",
db_name: 'Nom de la base de données',
desc: "Créez une base de données sur votre serveur et définissez les informations d'identification à l'aide du formulaire ci-dessous."
},
permissions: {
permissions: 'Les permissions',
permission_desc: "Vous trouverez ci-dessous la liste des autorisations de dossier requises pour le fonctionnement de l'application. Si la vérification des autorisations échoue, veillez à mettre à jour vos autorisations de dossier."
},
mail: {
host: 'Mail Host',
port: 'Port mail',
driver: 'Pilote de courrier',
password: 'Mot de passe mail',
username: "Mail Nom d'utilisateur",
mail_config: 'Configuration du courrier',
encryption: 'Chiffrement du courrier',
mail_config_desc: "Les détails ci-dessous seront utilisés pour mettre à jour l'environnement de messagerie. Aussi, vous pouvez modifier les détails à tout moment après la connexion."
},
req: {
system_req: 'Configuration requise',
php_req_version: 'Php (version {version} nécessaire)',
check_req: 'Vérifier les exigences',
system_req_desc: 'Crater a quelques exigences de serveur. Assurez-vous que votre serveur dispose de la version PHP requise et de toutes les extensions mentionnées ci-dessous.'
},
errors: {
migrate_failed: 'Migration impossible',
database_variables_save_error: 'Impossible de se connecter à la base de données avec les valeurs fournies.',
mail_variables_save_error: 'La configuration du courrier électronique a échoué.',
connection_failed: 'La connexion à la base de données a échoué'
},
success: {
mail_variables_save_successfully: 'Email configuré avec succès',
database_variables_save_successfully: 'Base de données configurée avec succès.'
}
}, },
layout_login: { layout_login: {
copyright_crater: 'Copyright @ Crater - 2019', copyright_crater: 'Copyright @ Crater - 2019',
@ -706,7 +751,9 @@ export default {
payment_greater_than_due_amount: 'Le paiement entré est plus que le montant dû de cette facture.', payment_greater_than_due_amount: 'Le paiement entré est plus que le montant dû de cette facture.',
quantity_maxlength: 'La quantité ne doit pas dépasser 10 chiffres.', quantity_maxlength: 'La quantité ne doit pas dépasser 10 chiffres.',
price_maxlength: 'Le prix ne doit pas dépasser 10 chiffres.', price_maxlength: 'Le prix ne doit pas dépasser 10 chiffres.',
price_minvalue: 'Le prix doit être supérieur à 0 chiffre',
amount_maxlength: 'Le montant ne doit pas dépasser 10 chiffres.', amount_maxlength: 'Le montant ne doit pas dépasser 10 chiffres.',
amount_minvalue: 'Le montant doit être supérieur à 0 chiffre',
description_maxlength: 'La description ne doit pas dépasser 255 caractères.', description_maxlength: 'La description ne doit pas dépasser 255 caractères.',
maximum_options_error: 'Maximum de {max} options sélectionnées. Commencez par supprimer une option sélectionnée pour en sélectionner une autre.', maximum_options_error: 'Maximum de {max} options sélectionnées. Commencez par supprimer une option sélectionnée pour en sélectionner une autre.',
notes_maxlength: 'Les notes ne doivent pas dépasser 255 caractères.', notes_maxlength: 'Les notes ne doivent pas dépasser 255 caractères.',

View File

@ -71,6 +71,7 @@ import Preferences from './views/settings/Preferences.vue'
import UserProfile from './views/settings/UserProfile.vue' import UserProfile from './views/settings/UserProfile.vue'
import TaxTypes from './views/settings/TaxTypes.vue' import TaxTypes from './views/settings/TaxTypes.vue'
import ExpenseCategory from './views/settings/ExpenseCategory.vue' import ExpenseCategory from './views/settings/ExpenseCategory.vue'
import MailConfig from './views/settings/MailConfig.vue'
import Wizard from './views/wizard/Index.vue' import Wizard from './views/wizard/Index.vue'
@ -327,6 +328,11 @@ const routes = [
name: 'expense.category', name: 'expense.category',
component: ExpenseCategory component: ExpenseCategory
}, },
{
path: 'mail-configuration',
name: 'mailconfig',
component: MailConfig
},
{ {
path: 'notifications', path: 'notifications',
name: 'notifications', name: 'notifications',

View File

@ -130,7 +130,7 @@ export const markAsRejected = ({ commit, dispatch, state }, data) => {
export const markAsSent = ({ commit, dispatch, state }, data) => { export const markAsSent = ({ commit, dispatch, state }, data) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
window.axios.post(`/api/estimates/sent`, data).then((response) => { window.axios.post(`/api/estimates/mark-as-sent`, data).then((response) => {
// commit(types.UPDATE_INVOICE, response.data) // commit(types.UPDATE_INVOICE, response.data)
resolve(response) resolve(response)
}).catch((err) => { }).catch((err) => {

View File

@ -96,6 +96,7 @@
<line-chart <line-chart
v-if="isLoaded" v-if="isLoaded"
:format-money="$utils.formatMoney" :format-money="$utils.formatMoney"
:format-graph-money="$utils.formatGraphMoney"
:invoices="getChartInvoices" :invoices="getChartInvoices"
:expenses="getChartExpenses" :expenses="getChartExpenses"
:receipts="getReceiptTotals" :receipts="getReceiptTotals"

View File

@ -688,7 +688,7 @@ export default {
isValid = false isValid = false
} }
}) })
if (this.$v.newEstimate.$invalid === false && isValid === true) { if (!this.$v.selectedCustomer.$invalid && this.$v.newEstimate.$invalid === false && isValid === true) {
return true return true
} }
return false return false

View File

@ -28,6 +28,7 @@
@select="onSelectItem" @select="onSelectItem"
@deselect="deselectItem" @deselect="deselectItem"
@onDesriptionInput="$v.item.description.$touch()" @onDesriptionInput="$v.item.description.$touch()"
@onSelectItem="isSelected = true"
/> />
</div> </div>
</td> </td>
@ -193,13 +194,17 @@ export default {
prefix: '$ ', prefix: '$ ',
precision: 2, precision: 2,
masked: false masked: false
} },
isSelected: false
} }
}, },
computed: { computed: {
...mapGetters('item', [ ...mapGetters('item', [
'items' 'items'
]), ]),
...mapGetters('modal', [
'modalActive'
]),
...mapGetters('currency', [ ...mapGetters('currency', [
'defaultCurrencyForInput' 'defaultCurrencyForInput'
]), ]),
@ -284,6 +289,11 @@ export default {
if (this.item.discount_type === 'percentage') { if (this.item.discount_type === 'percentage') {
this.item.discount_val = (this.item.discount * newValue) / 100 this.item.discount_val = (this.item.discount * newValue) / 100
} }
},
modalActive (val) {
if (!val) {
this.isSelected = false
}
} }
}, },
validations () { validations () {
@ -313,7 +323,11 @@ export default {
}, },
created () { created () {
window.hub.$on('checkItems', this.validateItem) window.hub.$on('checkItems', this.validateItem)
window.hub.$on('newItem', this.onSelectItem) window.hub.$on('newItem', (val) => {
if (!this.item.item_id && this.modalActive && this.isSelected) {
this.onSelectItem(val)
}
})
}, },
methods: { methods: {
updateTax (data) { updateTax (data) {

View File

@ -126,6 +126,7 @@ export default {
this.$emit('search', val) this.$emit('search', val)
}, },
openItemModal () { openItemModal () {
this.$emit('onSelectItem')
this.openModal({ this.openModal({
'title': 'Add Item', 'title': 'Add Item',
'componentName': 'ItemModal' 'componentName': 'ItemModal'

View File

@ -92,13 +92,14 @@
<money <money
v-model="amount" v-model="amount"
v-bind="defaultCurrencyForInput" v-bind="defaultCurrencyForInput"
:class="{'invalid' : $v.formData.amount.$error}"
class="input-field" class="input-field"
@input="$v.formData.amount.$touch()"
/> />
</div> </div>
<div v-if="$v.formData.amount.$error"> <div v-if="$v.formData.amount.$error">
<span v-if="!$v.formData.amount.required" class="text-danger">{{ $t('validation.required') }}</span> <span v-if="!$v.formData.amount.required" class="text-danger">{{ $t('validation.required') }}</span>
<span v-if="!$v.formData.amount.maxLength" class="text-danger">{{ $t('validation.amount_maxlength') }}</span> <span v-if="!$v.formData.amount.maxLength" class="text-danger">{{ $t('validation.amount_maxlength') }}</span>
<span v-if="!$v.formData.amount.maxValue" class="text-danger">{{ $t('validation.amount_minvalue') }}</span>
</div> </div>
</div> </div>
<div class="form-group col-sm-6"> <div class="form-group col-sm-6">

View File

@ -519,14 +519,6 @@ export default {
...mapActions('item', [ ...mapActions('item', [
'fetchItems' 'fetchItems'
]), ]),
isEmpty (obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
return false
}
}
return true
},
selectFixed () { selectFixed () {
if (this.newInvoice.discount_type === 'fixed') { if (this.newInvoice.discount_type === 'fixed') {
return return

View File

@ -28,6 +28,7 @@
@select="onSelectItem" @select="onSelectItem"
@deselect="deselectItem" @deselect="deselectItem"
@onDesriptionInput="$v.item.description.$touch()" @onDesriptionInput="$v.item.description.$touch()"
@onSelectItem="isSelected = true"
/> />
</div> </div>
</td> </td>
@ -194,13 +195,17 @@ export default {
prefix: '$ ', prefix: '$ ',
precision: 2, precision: 2,
masked: false masked: false
} },
isSelected: false
} }
}, },
computed: { computed: {
...mapGetters('item', [ ...mapGetters('item', [
'items' 'items'
]), ]),
...mapGetters('modal', [
'modalActive'
]),
...mapGetters('currency', [ ...mapGetters('currency', [
'defaultCurrencyForInput' 'defaultCurrencyForInput'
]), ]),
@ -285,6 +290,11 @@ export default {
if (this.item.discount_type === 'percentage') { if (this.item.discount_type === 'percentage') {
this.item.discount_val = (this.item.discount * newValue) / 100 this.item.discount_val = (this.item.discount * newValue) / 100
} }
},
modalActive (val) {
if (!val) {
this.isSelected = false
}
} }
}, },
validations () { validations () {
@ -314,7 +324,11 @@ export default {
}, },
created () { created () {
window.hub.$on('checkItems', this.validateItem) window.hub.$on('checkItems', this.validateItem)
window.hub.$on('newItem', this.onSelectItem) window.hub.$on('newItem', (val) => {
if (!this.item.item_id && this.modalActive && this.isSelected) {
this.onSelectItem(val)
}
})
}, },
methods: { methods: {
updateTax (data) { updateTax (data) {

View File

@ -115,6 +115,7 @@ export default {
this.$emit('search', val) this.$emit('search', val)
}, },
openItemModal () { openItemModal () {
this.$emit('onSelectItem')
this.openModal({ this.openModal({
'title': 'Add Item', 'title': 'Add Item',
'componentName': 'ItemModal' 'componentName': 'ItemModal'

View File

@ -34,16 +34,16 @@
<label>{{ $t('items.price') }}</label><span class="text-danger"> *</span> <label>{{ $t('items.price') }}</label><span class="text-danger"> *</span>
<div class="base-input"> <div class="base-input">
<money <money
:invalid="$v.formData.price.$error" :class="{'invalid' : $v.formData.price.$error}"
v-model="price" v-model="price"
v-bind="defaultCurrencyForInput" v-bind="defaultCurrencyForInput"
class="input-field" class="input-field"
@input="$v.formData.price.$touch()"
/> />
</div> </div>
<div v-if="$v.formData.price.$error"> <div v-if="$v.formData.price.$error">
<span v-if="!$v.formData.price.required" class="text-danger">{{ $t('validation.required') }} </span> <span v-if="!$v.formData.price.required" class="text-danger">{{ $t('validation.required') }} </span>
<span v-if="!$v.formData.price.maxLength" class="text-danger">{{ $t('validation.price_maxlength') }}</span> <span v-if="!$v.formData.price.maxLength" class="text-danger">{{ $t('validation.price_maxlength') }}</span>
<span v-if="!$v.formData.price.minValue" class="text-danger">{{ $t('validation.price_minvalue') }}</span>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -93,6 +93,7 @@
import { validationMixin } from 'vuelidate' import { validationMixin } from 'vuelidate'
import { mapActions, mapGetters } from 'vuex' import { mapActions, mapGetters } from 'vuex'
const { required, minLength, numeric, alpha, minValue, maxLength } = require('vuelidate/lib/validators') const { required, minLength, numeric, alpha, minValue, maxLength } = require('vuelidate/lib/validators')
export default { export default {
mixins: { mixins: {
validationMixin validationMixin

View File

@ -48,7 +48,7 @@
</div> </div>
<div class="col-sm-8 reports-tab-container"> <div class="col-sm-8 reports-tab-container">
<iframe :src="getReportUrl" class="reports-frame-style"/> <iframe :src="getReportUrl" class="reports-frame-style"/>
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank"> <a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span> <font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
</a> </a>
</div> </div>
@ -179,6 +179,11 @@ export default {
setRangeToCustom () { setRangeToCustom () {
this.selectedRange = 'Custom' this.selectedRange = 'Custom'
}, },
async viewReportsPDF () {
let data = await this.getReports()
window.open(this.getReportUrl, '_blank')
return data
},
async getReports (isDownload = false) { async getReports (isDownload = false) {
this.$v.range.$touch() this.$v.range.$touch()
this.$v.formData.$touch() this.$v.formData.$touch()

View File

@ -48,7 +48,7 @@
</div> </div>
<div class="col-sm-8 reports-tab-container"> <div class="col-sm-8 reports-tab-container">
<iframe :src="getReportUrl" class="reports-frame-style"/> <iframe :src="getReportUrl" class="reports-frame-style"/>
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank"> <a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span> <font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
</a> </a>
</div> </div>
@ -184,6 +184,11 @@ export default {
setRangeToCustom () { setRangeToCustom () {
this.selectedRange = 'Custom' this.selectedRange = 'Custom'
}, },
async viewReportsPDF () {
let data = await this.getReports()
window.open(this.getReportUrl, '_blank')
return data
},
async getReports (isDownload = false) { async getReports (isDownload = false) {
this.$v.range.$touch() this.$v.range.$touch()
this.$v.formData.$touch() this.$v.formData.$touch()

View File

@ -70,7 +70,7 @@
</div> </div>
<div class="col-sm-8 reports-tab-container"> <div class="col-sm-8 reports-tab-container">
<iframe :src="getReportUrl" class="reports-frame-style"/> <iframe :src="getReportUrl" class="reports-frame-style"/>
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank"> <a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span> <font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
</a> </a>
</div> </div>
@ -217,6 +217,11 @@ export default {
this.url = `${this.itemsSiteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}` this.url = `${this.itemsSiteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
return true return true
}, },
async viewReportsPDF () {
let data = await this.getReports()
window.open(this.getReportUrl, '_blank')
return data
},
async getReports (isDownload = false) { async getReports (isDownload = false) {
this.$v.range.$touch() this.$v.range.$touch()
this.$v.formData.$touch() this.$v.formData.$touch()

View File

@ -48,7 +48,7 @@
</div> </div>
<div class="col-sm-8 reports-tab-container"> <div class="col-sm-8 reports-tab-container">
<iframe :src="getReportUrl" class="reports-frame-style"/> <iframe :src="getReportUrl" class="reports-frame-style"/>
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank"> <a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span> <font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
</a> </a>
</div> </div>
@ -179,6 +179,11 @@ export default {
setRangeToCustom () { setRangeToCustom () {
this.selectedRange = 'Custom' this.selectedRange = 'Custom'
}, },
async viewReportsPDF () {
let data = await this.getReports()
window.open(this.getReportUrl, '_blank')
return data
},
async getReports (isDownload = false) { async getReports (isDownload = false) {
this.$v.range.$touch() this.$v.range.$touch()
this.$v.formData.$touch() this.$v.formData.$touch()

View File

@ -0,0 +1,213 @@
<template>
<div class="setting-main-container">
<div class="card setting-card">
<div class="page-header">
<h3 class="page-title">{{ $t('settings.mail.mail_config') }}</h3>
<p class="page-sub-title">
{{ $t('settings.mail.mail_config_desc') }}
</p>
</div>
<form action="" @submit.prevent="saveEmailConfig()">
<div class="row my-2 mt-5">
<div class="col-md-6 my-2">
<label class="form-label">{{ $t('settings.mail.driver') }}</label>
<span class="text-danger"> *</span>
<base-select
v-model="mailConfigData.mail_driver"
:invalid="$v.mailConfigData.mail_driver.$error"
:options="mail_drivers"
:searchable="true"
:show-labels="false"
@change="$v.mailConfigData.mail_driver.$touch()"
/>
<div v-if="$v.mailConfigData.mail_driver.$error">
<span v-if="!$v.mailConfigData.mail_driver.required" class="text-danger">
{{ $tc('validation.required') }}
</span>
</div>
</div>
<div class="col-md-6 my-2">
<label class="form-label">{{ $t('settings.mail.host') }}</label>
<span class="text-danger"> *</span>
<base-input
:invalid="$v.mailConfigData.mail_host.$error"
v-model.trim="mailConfigData.mail_host"
type="text"
name="mail_host"
@input="$v.mailConfigData.mail_host.$touch()"
/>
<div v-if="$v.mailConfigData.mail_host.$error">
<span v-if="!$v.mailConfigData.mail_host.required" class="text-danger">
{{ $tc('validation.required') }}
</span>
</div>
</div>
</div>
<div class="row my-2">
<div class="col-md-6 my-2">
<label class="form-label">{{ $t('settings.mail.username') }}</label>
<span class="text-danger"> *</span>
<base-input
:invalid="$v.mailConfigData.mail_username.$error"
v-model.trim="mailConfigData.mail_username"
type="text"
name="db_name"
@input="$v.mailConfigData.mail_username.$touch()"
/>
<div v-if="$v.mailConfigData.mail_username.$error">
<span v-if="!$v.mailConfigData.mail_username.required" class="text-danger">
{{ $tc('validation.required') }}
</span>
</div>
</div>
<div class="col-md-6 my-2">
<label class="form-label">{{ $t('settings.mail.password') }}</label>
<span class="text-danger"> *</span>
<base-input
:invalid="$v.mailConfigData.mail_password.$error"
v-model.trim="mailConfigData.mail_password"
type="mail_password"
name="name"
@input="$v.mailConfigData.mail_password.$touch()"
/>
<div v-if="$v.mailConfigData.mail_password.$error">
<span v-if="!$v.mailConfigData.mail_password.required" class="text-danger">
{{ $tc('validation.required') }}
</span>
</div>
</div>
</div>
<div class="row my-2">
<div class="col-md-6 my-2">
<label class="form-label">{{ $t('settings.mail.port') }}</label>
<span class="text-danger"> *</span>
<base-input
:invalid="$v.mailConfigData.mail_port.$error"
v-model.trim="mailConfigData.mail_port"
type="text"
name="mail_port"
@input="$v.mailConfigData.mail_port.$touch()"
/>
<div v-if="$v.mailConfigData.mail_port.$error">
<span v-if="!$v.mailConfigData.mail_port.required" class="text-danger">
{{ $tc('validation.required') }}
</span>
<span v-if="!$v.mailConfigData.mail_port.numeric" class="text-danger">
{{ $tc('validation.numbers_only') }}
</span>
</div>
</div>
<div class="col-md-6 my-2">
<label class="form-label">{{ $t('settings.mail.encryption') }}</label>
<span class="text-danger"> *</span>
<base-input
:invalid="$v.mailConfigData.mail_encryption.$error"
v-model.trim="mailConfigData.mail_encryption"
type="text"
name="name"
@input="$v.mailConfigData.mail_encryption.$touch()"
/>
<div v-if="$v.mailConfigData.mail_encryption.$error">
<span v-if="!$v.mailConfigData.mail_encryption.required" class="text-danger">
{{ $tc('validation.required') }}
</span>
</div>
</div>
</div>
<base-button
:loading="loading"
class="pull-right mt-5"
icon="save"
color="theme"
type="submit"
>
{{ $t('wizard.save_cont') }}
</base-button>
</form>
</div>
</div>
</template>
<script>
import MultiSelect from 'vue-multiselect'
import { validationMixin } from 'vuelidate'
import Ls from '../../services/ls'
const { required, email, numeric } = require('vuelidate/lib/validators')
export default {
components: {
MultiSelect
},
mixins: [validationMixin],
data () {
return {
mailConfigData: {
mail_driver: 'smtp',
mail_host: 'mailtrap.io',
mail_port: 2525,
mail_username: 'cc3c64516febd4',
mail_password: 'e6a0176301f587',
mail_encryption: 'tls'
},
loading: false,
mail_drivers: []
}
},
validations: {
mailConfigData: {
mail_driver: {
required
},
mail_host: {
required
},
mail_port: {
required,
numeric
},
mail_username: {
required
},
mail_password: {
required
},
mail_encryption: {
required
}
}
},
mounted () {
// this.getMailDrivers()
},
methods: {
async getMailDrivers () {
this.loading = true
let response = await window.axios.get('/api/admin/onboarding/environment/mail')
if (response.data) {
this.mail_drivers = response.data
this.loading = false
}
},
async saveEmailConfig () {
this.$v.mailConfigData.$touch()
if (this.$v.mailConfigData.$invalid) {
return true
}
this.loading = true
try {
let response = await window.axios.post('/api/admin/onboarding/environment/mail', this.mailConfigData)
if (response.data.success) {
window.toastr['success'](this.$t('wizard.success.' + response.data.success))
} else {
window.toastr['error'](this.$t('wizard.errors.' + response.data.error))
}
this.loading = false
return true
} catch (e) {
window.toastr['error']('Something went wrong')
}
}
}
}
</script>

View File

@ -113,7 +113,11 @@
<h3 class="page-title">{{ $t('settings.preferences.discount_setting') }}</h3> <h3 class="page-title">{{ $t('settings.preferences.discount_setting') }}</h3>
<div class="flex-box"> <div class="flex-box">
<div class="left"> <div class="left">
<base-switch v-model="discount_per_item" class="btn-switch" @change="setDiscount" /> <base-switch
v-model="discount_per_item"
class="btn-switch"
@change="setDiscount"
/>
</div> </div>
<div class="right ml-15"> <div class="right ml-15">
<p class="box-title"> {{ $t('settings.preferences.discount_per_item') }} </p> <p class="box-title"> {{ $t('settings.preferences.discount_per_item') }} </p>

View File

@ -63,6 +63,12 @@ export default {
icon: 'list-alt', icon: 'list-alt',
iconType: 'far' iconType: 'far'
}, },
{
link: '/admin/settings/mail-configuration',
title: 'settings.mail.mail_config',
icon: 'envelope',
iconType: 'fa'
},
{ {
link: '/admin/settings/notifications', link: '/admin/settings/notifications',
title: 'settings.menu_title.notifications', title: 'settings.menu_title.notifications',

View File

@ -109,15 +109,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row mt-5">
<base-button <base-button
:loading="loading" :loading="loading"
class="pull-right mt-5" class="pull-right"
icon="save" icon="save"
color="theme" color="theme"
type="submit" type="submit"
> >
{{ $t('wizard.save_cont') }} {{ $t('wizard.save_cont') }}
</base-button> </base-button>
<base-button
:loading="loading"
class="pull-right ml-4"
outline
color="theme"
@click="$emit('next')"
>
{{ $t('wizard.skip') }}
</base-button>
</div>
</form> </form>
</div> </div>
</template> </template>
@ -137,10 +148,10 @@ export default {
mailConfigData: { mailConfigData: {
mail_driver: 'smtp', mail_driver: 'smtp',
mail_host: 'mailtrap.io', mail_host: 'mailtrap.io',
mail_port: 2525, mail_port: null,
mail_username: 'cc3c64516febd4', mail_username: null,
mail_password: 'e6a0176301f587', mail_password: null,
mail_encryption: 'tls' mail_encryption: null
}, },
loading: false, loading: false,
mail_drivers: [] mail_drivers: []

View File

@ -21,6 +21,7 @@
.report-view-button { .report-view-button {
display: none; display: none;
color: $btn-secondary-color;
} }
.report-fields-container { .report-fields-container {
@ -61,8 +62,13 @@
display: none; display: none;
} }
.report-submit-button-container {
display: none;
}
.report-view-button { .report-view-button {
display: flex; display: flex;
color: $btn-secondary-color !important;
justify-content: center justify-content: center
} }

View File

@ -72,6 +72,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 60px; padding-top: 60px;
padding-bottom: 60px;
} }
.address { .address {
@ -244,6 +245,8 @@
margin-top: 35px; margin-top: 35px;
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
padding: 0px 30px 0 30px; padding: 0px 30px 0 30px;
page-break-before: avoid;
page-break-after: auto;
} }
.table2 hr { .table2 hr {
@ -257,7 +260,7 @@
padding: 5px; padding: 5px;
} }
tr.main-table-header td { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
@ -284,28 +287,33 @@
padding-bottom: 8px; padding-bottom: 8px;
} }
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 { .table3 {
border: 1px solid #EAF1FB;
border-top: none; border-top: none;
padding-right: 30px;
box-sizing: border-box; box-sizing: border-box;
width: 230px; width: 630px;
height: 100px; page-break-inside: avoid;
position: absolute; page-break-before: auto;
right: -25; page-break-after: auto;
} }
.text-per-item-table3 { .total-border-left {
border: 1px solid #EAF1FB; border: 1px solid #E8E8E8!important;
border-top: none; border-right: 0px !important;
padding-right: 30px; padding-top: 0px;
box-sizing: border-box; padding:8px !important;
width: 260px;
/* height: 100px; */
position: absolute;
right: -25;
} }
.total-border-right {
border: 1px solid #E8E8E8!important;
border-left: 0px !important;
padding-top: 0px;
padding:8px !important;
}
.inv-item { .inv-item {
border-color: #d9d9d9; border-color: #d9d9d9;
} }
@ -323,6 +331,30 @@
color:rgba(0, 0, 0, 0.85); color:rgba(0, 0, 0, 0.85);
} }
.notes {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
margin-left: 30px;
width: 442px;
text-align: left;
}
.notes-label {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
color: #040405;
width: 108px;
height: 19.87px;
padding-bottom: 10px;
}
</style> </style>
</head> </head>
@ -380,6 +412,7 @@
<div style="clear: both;"></div> <div style="clear: both;"></div>
</div> </div>
@include('app.pdf.estimate.partials.table') @include('app.pdf.estimate.partials.table')
@include('app.pdf.estimate.partials.notes')
</div> </div>
</body> </body>
</html> </html>

View File

@ -74,6 +74,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 110px; padding-top: 110px;
padding-bottom: 60px;
} }
.address { .address {
@ -245,6 +246,8 @@
margin-top: 200px; margin-top: 200px;
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
padding: 0px 30px 0 30px; padding: 0px 30px 0 30px;
page-break-before: avoid;
page-break-after: auto;
} }
.table2 hr { .table2 hr {
@ -258,7 +261,7 @@
padding: 5px; padding: 5px;
} }
tr.main-table-header td { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
@ -295,27 +298,21 @@
padding-bottom: 8px; padding-bottom: 8px;
} }
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 { .table3 {
border: 1px solid #EAF1FB; border: 1px solid #EAF1FB;
border-top: none; border-top: none;
padding-right: 30px;
box-sizing: border-box; box-sizing: border-box;
width: 230px; width: 630px;
height: 100px; page-break-inside: avoid;
position: absolute; page-break-before: auto;
right: -25; page-break-after: auto;
} }
.text-per-item-table3 {
border: 1px solid #EAF1FB;
border-top: none;
padding-right: 30px;
box-sizing: border-box;
width: 260px;
/* height: 100px; */
position: absolute;
right: -25;
}
.inv-item { .inv-item {
border-color: #d9d9d9; border-color: #d9d9d9;
@ -361,6 +358,32 @@
margin-bottom:1px; margin-bottom:1px;
margin-top:0; margin-top:0;
} }
.notes {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
margin-left: 30px;
width: 442px;
text-align: left;
}
.notes-label {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
color: #040405;
width: 108px;
height: 19.87px;
padding-bottom: 10px;
}
</style> </style>
</head> </head>
<body> <body>
@ -402,6 +425,7 @@
</div> </div>
</div> </div>
@include('app.pdf.estimate.partials.table') @include('app.pdf.estimate.partials.table')
@include('app.pdf.estimate.partials.notes')
</div> </div>
</body> </body>
</html> </html>

View File

@ -80,6 +80,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 110px; padding-top: 110px;
padding-bottom: 60px;
} }
.address { .address {
@ -233,7 +234,7 @@
.main-table-header { .main-table-header {
border-bottom: 1px solid red; border-bottom: 1px solid red;
} }
tr.main-table-header td { tr.main-table-header th {
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-size: 12px; font-size: 12px;
@ -249,6 +250,8 @@
margin-top: 188px; margin-top: 188px;
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
padding: 0px 30px 0 30px; padding: 0px 30px 0 30px;
page-break-before: avoid;
page-break-after: auto;
} }
.table2 hr { .table2 hr {
@ -284,26 +287,19 @@
padding-bottom: 8px; padding-bottom: 8px;
} }
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 { .table3 {
border: 1px solid #EAF1FB; border: 1px solid #EAF1FB;
border-top: none; border-top: none;
padding-right: 30px;
box-sizing: border-box; box-sizing: border-box;
width: 230px; width: 630px;
height: 100px; page-break-inside: avoid;
position: absolute; page-break-before: auto;
right: -25; page-break-after: auto;
}
.text-per-item-table3 {
border: 1px solid #EAF1FB;
border-top: none;
padding-right: 30px;
box-sizing: border-box;
width: 260px;
/* height: 100px; */
position: absolute;
right: -25;
} }
td.estimate-total1 { td.estimate-total1 {
@ -370,6 +366,32 @@
border-bottom:1px solid #E8E8E8; border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8; border-top:1px solid #E8E8E8;
} }
.notes {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
margin-left: 30px;
width: 442px;
text-align: left;
}
.notes-label {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
color: #040405;
width: 108px;
height: 19.87px;
padding-bottom: 10px;
}
</style> </style>
</head> </head>
<body> <body>
@ -427,6 +449,7 @@
</div> </div>
</div> </div>
@include('app.pdf.estimate.partials.table') @include('app.pdf.estimate.partials.table')
@include('app.pdf.estimate.partials.notes')
</div> </div>
</body> </body>
</html> </html>

View File

@ -0,0 +1,6 @@
<div class="notes">
<div class="notes-label">
Notes
</div>
{{$estimate->notes}}
</div>

View File

@ -1,21 +1,27 @@
<table width="100%" class="table2" cellspacing="0" border="0"> <table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header"> <tr class="main-table-header">
<td width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</td> @if($estimate->discount_per_item === 'NO')
<td width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</td> <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
<td width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</td> @else
<td width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</td> <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
<td width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</td> @endif
<th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th>
@if($estimate->discount_per_item === 'YES')
<th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th>
@endif
<th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
</tr> </tr>
@foreach ($estimate->items as $item) @foreach ($estimate->items as $item)
<tr class="item-details"> <tr class="item-details">
<td width="40%" class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px">
<span>{{ $item->name }}</span><br> <span>{{ $item->name }}</span><br>
<span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span>
</td> </td>
<td width="17%" class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td>
<td width="18%" class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> <td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td>
{{-- <td width="10%" class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px">{{$item->discount/100}}%</td> --}} @if($estimate->discount_per_item === 'YES')
<td width="10%" class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> <td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px">
@if($item->discount_type === 'fixed') @if($item->discount_type === 'fixed')
{{$item->discount_val/100}} {{$item->discount_val/100}}
@endif @endif
@ -23,25 +29,26 @@
{{$item->discount}}% {{$item->discount}}%
@endif @endif
</td> </td>
<td width="15%" class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> @endif
<td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td>
</tr> </tr>
@endforeach @endforeach
</table> </table>
<table width="100%" cellspacing="0px" border="0" class="text-per-item-table3 @if(count($estimate->items) > 12) page-break @endif"> <table width="100%" style="margin-left:420px" cellspacing="0px" border="0" class="table3">
<tr> <tr>
<td class="no-borde" style="color: #55547A; padding-left:10px; line-height: 18px; font-size:12px;">Subtotal</td> <td class="no-borde" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td>
<td class="no-border items" <td class="no-border items"
style="padding-right:10px; text-align: right; line-height: 18px; font-size:12px; color: #040405; font-weight: 500;">{!! format_money_pdf($estimate->sub_total) !!}</td> style="padding-right:10px; text-align: right; font-size:12px; color: #040405; font-weight: 500;">{!! format_money_pdf($estimate->sub_total) !!}</td>
</tr> </tr>
@if ($estimate->tax_per_item === 'YES') @if ($estimate->tax_per_item === 'YES')
@for ($i = 0; $i < count($labels); $i++) @for ($i = 0; $i < count($labels); $i++)
<tr> <tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; line-height: 18px; color: #55547A;"> <td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$labels[$i]}} {{$labels[$i]}}
</td> </td>
<td class="no-border items padd8" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; line-height: 18px; color: #040405"> <td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($taxes[$i]) !!} {!! format_money_pdf($taxes[$i]) !!}
</td> </td>
</tr> </tr>
@ -49,10 +56,10 @@
@else @else
@foreach ($estimate->taxes as $tax) @foreach ($estimate->taxes as $tax)
<tr> <tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; line-height: 18px; color: #55547A;"> <td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$tax->name.' ('.$tax->percent.'%)'}} {{$tax->name.' ('.$tax->percent.'%)'}}
</td> </td>
<td class="no-border items padd8" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; line-height: 18px; color: #040405"> <td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($tax->amount) !!} {!! format_money_pdf($tax->amount) !!}
</td> </td>
</tr> </tr>
@ -62,27 +69,31 @@
@if ($estimate->discount_per_item === 'NO') @if ($estimate->discount_per_item === 'NO')
<tr> <tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;"> <td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
Discount Discount ({{$estimate->discount}}%)
</td> </td>
<td class="no-border items padd8" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405"> <td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
@if($estimate->discount_type === 'fixed') @if($estimate->discount_type === 'fixed')
{!! format_money_pdf($estimate->discount_val) !!} {!! format_money_pdf($estimate->discount_val) !!}
@endif @endif
@if($estimate->discount_type === 'percentage') @if($estimate->discount_type === 'percentage')
{{$estimate->discount}}% ({!! format_money_pdf($estimate->discount_val) !!}) {!! format_money_pdf($estimate->discount_val) !!}
@endif @endif
</td> </td>
</tr> </tr>
@endif @endif
<tr>
<td style="padding:3px 0px"></td>
<td style="padding:3px 0px"></td>
</tr>
<tr> <tr>
<td class="no-border total-border-left" <td class="no-border total-border-left"
style="padding-left:10px; padding-bottom:10px; text-align:left; padding-top:20px; font-size:12px; line-height: 18px; color: #55547A;" style="padding-left:10px; padding-bottom:10px; text-align:left; padding-top:20px; font-size:12px; color: #55547A;"
> >
<label class="total-bottom"> Total </label> <label class="total-bottom"> Total </label>
</td> </td>
<td <td
class="no-border total-border-right items padd8" class="no-border total-border-right items padd8"
style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; line-height: 18px; padding-top:20px; color: #5851DB" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; padding-top:20px; color: #5851DB"
> >
{!! format_money_pdf($estimate->total)!!} {!! format_money_pdf($estimate->total)!!}
</td> </td>

View File

@ -72,6 +72,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 60px; padding-top: 60px;
padding-bottom: 60px;
} }
.address { .address {
@ -244,6 +245,8 @@
margin-top: 35px; margin-top: 35px;
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
padding: 0px 30px 0 30px; padding: 0px 30px 0 30px;
page-break-before: avoid;
page-break-after: auto;
} }
.table2 hr { .table2 hr {
@ -257,7 +260,7 @@
padding: 5px; padding: 5px;
} }
tr.main-table-header td { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
@ -284,26 +287,36 @@
padding-bottom: 8px; padding-bottom: 8px;
} }
.table3 { .padd2 {
border: 1px solid #EAF1FB; padding-top: 2px;
border-top: none; padding-bottom: 2px;
padding-right: 30px;
box-sizing: border-box;
width: 230px;
height: 100px;
position: absolute;
right: -25;
} }
.text-per-item-table3 { .table3 {
border: 1px solid #EAF1FB; /* border: 1px solid #EAF1FB; */
border-top: none; border-top: none;
padding-right: 30px; /* padding-right: 30px; */
box-sizing: border-box; box-sizing: border-box;
width: 260px; width: 630px;
/* height: 100px; */ /* position: absolute;
position: absolute; right: -25; */
right: -25; page-break-inside: avoid;
page-break-before: auto;
page-break-after: auto;
}
.total-border-left {
border: 1px solid #E8E8E8!important;
border-right: 0px !important;
padding-top: 0px;
padding:8px !important;
}
.total-border-right {
border: 1px solid #E8E8E8!important;
border-left: 0px !important;
padding-top: 0px;
padding:8px !important;
} }
.inv-item { .inv-item {
@ -323,6 +336,30 @@
color:rgba(0, 0, 0, 0.85); color:rgba(0, 0, 0, 0.85);
} }
.notes {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
margin-left: 30px;
width: 442px;
text-align: left;
}
.notes-label {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
color: #040405;
width: 108px;
height: 19.87px;
padding-bottom: 10px;
}
</style> </style>
</head> </head>
@ -380,7 +417,10 @@
</div> </div>
<div style="clear: both;"></div> <div style="clear: both;"></div>
</div> </div>
<div style="position:relative">
@include('app.pdf.invoice.partials.table') @include('app.pdf.invoice.partials.table')
</div> </div>
@include('app.pdf.invoice.partials.notes')
</div>
</body> </body>
</html> </html>

View File

@ -74,6 +74,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 110px; padding-top: 110px;
padding-bottom: 60px;
} }
.address { .address {
@ -245,6 +246,8 @@
margin-top: 200px; margin-top: 200px;
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
padding: 0px 30px 0 30px; padding: 0px 30px 0 30px;
page-break-before: avoid;
page-break-after: auto;
} }
.table2 hr { .table2 hr {
@ -258,7 +261,7 @@
padding: 5px; padding: 5px;
} }
tr.main-table-header td { tr.main-table-header th {
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
@ -295,15 +298,19 @@
padding-bottom: 8px; padding-bottom: 8px;
} }
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 { .table3 {
border: 1px solid #EAF1FB; border: 1px solid #EAF1FB;
border-top: none; border-top: none;
padding-right: 30px;
box-sizing: border-box; box-sizing: border-box;
width: 230px; width: 630px;
height: 100px; page-break-inside: avoid;
position: absolute; page-break-before: auto;
right: -25; page-break-after: auto;
} }
.text-per-item-table3 { .text-per-item-table3 {
@ -361,6 +368,32 @@
margin-bottom:1px; margin-bottom:1px;
margin-top:0; margin-top:0;
} }
.notes {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
margin-left: 30px;
width: 442px;
text-align: left;
}
.notes-label {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
color: #040405;
width: 108px;
height: 19.87px;
padding-bottom: 10px;
}
</style> </style>
</head> </head>
<body> <body>
@ -403,6 +436,7 @@
</div> </div>
</div> </div>
@include('app.pdf.invoice.partials.table') @include('app.pdf.invoice.partials.table')
@include('app.pdf.invoice.partials.notes')
</div> </div>
</body> </body>
</html> </html>

View File

@ -80,6 +80,7 @@
.wrapper { .wrapper {
display: block; display: block;
padding-top: 110px; padding-top: 110px;
padding-bottom: 60px;
} }
.address { .address {
@ -233,7 +234,7 @@
.main-table-header { .main-table-header {
border-bottom: 1px solid red; border-bottom: 1px solid red;
} }
tr.main-table-header td { tr.main-table-header th {
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
font-size: 12px; font-size: 12px;
@ -249,6 +250,8 @@
margin-top: 188px; margin-top: 188px;
border-bottom: 1px solid #EAF1FB; border-bottom: 1px solid #EAF1FB;
padding: 0px 30px 0 30px; padding: 0px 30px 0 30px;
page-break-before: avoid;
page-break-after: auto;
} }
.table2 hr { .table2 hr {
@ -284,15 +287,19 @@
padding-bottom: 8px; padding-bottom: 8px;
} }
.padd2 {
padding-top: 2px;
padding-bottom: 2px;
}
.table3 { .table3 {
border: 1px solid #EAF1FB; border: 1px solid #EAF1FB;
border-top: none; border-top: none;
padding-right: 30px;
box-sizing: border-box; box-sizing: border-box;
width: 230px; width: 630px;
height: 100px; page-break-inside: avoid;
position: absolute; page-break-before: auto;
right: -25; page-break-after: auto;
} }
.text-per-item-table3 { .text-per-item-table3 {
@ -370,6 +377,32 @@
border-bottom:1px solid #E8E8E8; border-bottom:1px solid #E8E8E8;
border-top:1px solid #E8E8E8; border-top:1px solid #E8E8E8;
} }
.notes {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: 300;
font-size: 12px;
color: #595959;
margin-top: 15px;
margin-left: 30px;
width: 442px;
text-align: left;
}
.notes-label {
font-family: 'Roboto', sans-serif;
font-style: normal;
font-weight: normal;
font-size: 15px;
line-height: 22px;
letter-spacing: 0.05em;
color: #040405;
width: 108px;
height: 19.87px;
padding-bottom: 10px;
}
</style> </style>
</head> </head>
<body> <body>
@ -427,6 +460,7 @@
</div> </div>
</div> </div>
@include('app.pdf.invoice.partials.table') @include('app.pdf.invoice.partials.table')
@include('app.pdf.invoice.partials.notes')
</div> </div>
</body> </body>
</html> </html>

View File

@ -0,0 +1,6 @@
<div class="notes">
<div class="notes-label">
Notes
</div>
{{$invoice->notes}}
</div>

View File

@ -1,20 +1,27 @@
<table width="100%" class="table2" cellspacing="0" border="0"> <table width="100%" class="table2" cellspacing="0" border="0">
<tr class="main-table-header"> <tr class="main-table-header">
<td width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</td> @if($invoice->discount_per_item === 'NO')
<td width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</td> <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
<td width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</td> @else
<td width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</td> <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th>
<td width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</td> @endif
<th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th>
<th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th>
@if($invoice->discount_per_item === 'YES')
<th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th>
@endif
<th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th>
</tr> </tr>
@foreach ($invoice->items as $item) @foreach ($invoice->items as $item)
<tr class="item-details"> <tr class="item-details">
<td width="40%" class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px">
<span>{{ $item->name }}</span><br> <span>{{ $item->name }}</span><br>
<span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span>
</td> </td>
<td width="17%" class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td>
<td width="18%" class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> <td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td>
<td width="10%" class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> @if($invoice->discount_per_item === 'YES')
<td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px">
@if($item->discount_type === 'fixed') @if($item->discount_type === 'fixed')
{{$item->discount_val/100}} {{$item->discount_val/100}}
@endif @endif
@ -22,25 +29,26 @@
{{$item->discount}}% {{$item->discount}}%
@endif @endif
</td> </td>
<td width="15%" class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> @endif
<td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td>
</tr> </tr>
@endforeach @endforeach
</table> </table>
<table width="100%" cellspacing="0px" border="0" class="text-per-item-table3 @if(count($invoice->items) > 12) page-break @endif"> <table width="100%" cellspacing="0px" style="margin-left:420px" border="0" class="table3 @if(count($invoice->items) > 12) page-break @endif">
<tr> <tr>
<td class="no-borde" style="color: #55547A; padding-left:10px; line-height: 18px; font-size:12px;">Subtotal</td> <td class="no-borde" style="color: #55547A; padding-left:10px; font-size:12px;">Subtotal</td>
<td class="no-border items" <td class="no-border items"
style="padding-right:10px; text-align: right; line-height: 18px; font-size:12px; color: #040405; font-weight: 500;">{!! format_money_pdf($invoice->sub_total) !!}</td> style="padding-right:10px; text-align: right; font-size:12px; color: #040405; font-weight: 500;">{!! format_money_pdf($invoice->sub_total) !!}</td>
</tr> </tr>
@if ($invoice->tax_per_item === 'YES') @if ($invoice->tax_per_item === 'YES')
@for ($i = 0; $i < count($labels); $i++) @for ($i = 0; $i < count($labels); $i++)
<tr> <tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; line-height: 18px; color: #55547A;"> <td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$labels[$i]}} {{$labels[$i]}}
</td> </td>
<td class="no-border items padd8" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; line-height: 18px; color: #040405"> <td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($taxes[$i]) !!} {!! format_money_pdf($taxes[$i]) !!}
</td> </td>
</tr> </tr>
@ -48,10 +56,10 @@
@else @else
@foreach ($invoice->taxes as $tax) @foreach ($invoice->taxes as $tax)
<tr> <tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; line-height: 18px; color: #55547A;"> <td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
{{$tax->name.' ('.$tax->percent.'%)'}} {{$tax->name.' ('.$tax->percent.'%)'}}
</td> </td>
<td class="no-border items padd8" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; line-height: 18px; color: #040405"> <td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
{!! format_money_pdf($tax->amount) !!} {!! format_money_pdf($tax->amount) !!}
</td> </td>
</tr> </tr>
@ -61,27 +69,31 @@
@if ($invoice->discount_per_item === 'NO') @if ($invoice->discount_per_item === 'NO')
<tr> <tr>
<td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;"> <td class="no-border" style="padding-left:10px; text-align:left; font-size:12px; color: #55547A;">
Discount Discount ({{$invoice->discount}}%)
</td> </td>
<td class="no-border items padd8" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405"> <td class="no-border items padd2" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; color: #040405">
@if($invoice->discount_type === 'fixed') @if($invoice->discount_type === 'fixed')
{!! format_money_pdf($invoice->discount_val) !!} {!! format_money_pdf($invoice->discount_val) !!}
@endif @endif
@if($invoice->discount_type === 'percentage') @if($invoice->discount_type === 'percentage')
{{$invoice->discount}}% ({!! format_money_pdf($invoice->discount_val) !!}) {!! format_money_pdf($invoice->discount_val) !!}
@endif @endif
</td> </td>
</tr> </tr>
@endif @endif
<tr style="border: 1px solid;" > <tr>
<td style="padding:3px 0px"></td>
<td style="padding:3px 0px"></td>
</tr>
<tr>
<td class="no-border total-border-left" <td class="no-border total-border-left"
style="padding-left:10px; padding-bottom:10px; text-align:left; padding-top:20px; font-size:12px; line-height: 18px; color: #55547A;" style="padding-left:10px; padding-bottom:10px; text-align:left; padding-top:20px; font-size:12px; color: #55547A;"
> >
<label class="total-bottom"> Total </label> <label class="total-bottom"> Total </label>
</td> </td>
<td <td
class="no-border total-border-right items padd8" class="no-border total-border-right items padd8"
style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; line-height: 18px; padding-top:20px; color: #5851DB" style="padding-right:10px; font-weight: 500; text-align: right; font-size:12px; padding-top:20px; color: #5851DB"
> >
{!! format_money_pdf($invoice->total)!!} {!! format_money_pdf($invoice->total)!!}
</td> </td>