Do not prompt to update invoice client/team details when closing client/team modal.

Always pass invoice id when updating.
When changing team info re-prefill invoice team info.
This commit is contained in:
HenriT
2021-04-13 16:27:28 +03:00
parent 0a5d45e64b
commit e23e1f720e
13 changed files with 144 additions and 93 deletions

View File

@ -63,18 +63,18 @@ export default {
},
async promptUpdateInvoice() {
if (this.$route.name === 'invoice' && this.invoice.client_id === this.client.id) {
const confirmed = await this.$bvModal.msgBoxConfirm('Update client details on invoice?', {
/* const confirmed = await this.$bvModal.msgBoxConfirm('Update client details on invoice?', {
okTitle: 'Update',
cancelTitle: 'Dismiss',
cancelVariant: 'btn-link',
contentClass: 'bg-base dp--24',
});
if (confirmed) {
this.$store.dispatch('invoices/prefillClient', {
client: this.client,
invoice: this.invoice,
});
}
if (confirmed) { */
this.$store.dispatch('invoices/prefillClient', {
client: this.client,
invoiceId: this.invoice.id,
});
/* } */
}
},
},

View File

@ -65,7 +65,7 @@ export default {
clientSelected(client) {
this.$store.dispatch('invoices/prefillClient', {
client,
invoice: this.invoice,
invoiceId: this.invoice.id,
});
},
},

View File

@ -22,6 +22,7 @@ export default {
this.$store.dispatch('invoiceClientFields/updateInvoiceClientField', {
props,
fieldId: field.id,
invoiceId: this.invoice.id,
});
},
},

View File

@ -65,7 +65,10 @@ export default {
this.$store.dispatch('invoices/bookInvoice');
},
updateProp(props) {
this.$store.dispatch('invoices/updateInvoice', props);
this.$store.dispatch('invoices/updateInvoice', {
props,
invoiceId: this.invoice.id,
});
},
print() {
window.print();

View File

@ -101,7 +101,10 @@ export default {
this.$store.dispatch('invoices/getInvoice', this.$route.params.id);
},
updateProp(props) {
this.$store.dispatch('invoices/updateInvoice', props);
this.$store.dispatch('invoices/updateInvoice', {
props,
invoiceId: this.invoice.id,
});
},
addRow() {
this.$store.dispatch('invoiceRows/addRow', this.invoice.id);

View File

@ -55,6 +55,7 @@ export default {
this.$store.dispatch('invoiceRows/updateInvoiceRow', {
props,
id: this.row.id,
invoiceId: this.row.invoice_id,
});
},
async removeRow(row) {

View File

@ -22,6 +22,7 @@ export default {
this.$store.dispatch('invoiceTeamFields/updateInvoiceTeamField', {
props,
fieldId: field.id,
invoiceId: this.invoice.id,
});
},
},

View File

@ -29,6 +29,7 @@ export default {
},
...mapGetters({
team: 'teams/team',
invoice: 'invoices/invoice',
}),
},
mounted() {
@ -38,9 +39,25 @@ export default {
getTeam() {
this.$store.dispatch('teams/getTeam');
},
close() {
async close() {
await this.promptUpdateInvoice();
this.isOpen = false;
},
async promptUpdateInvoice() {
if (this.$route.name === 'invoice') {
/* const confirmed = await this.$bvModal.msgBoxConfirm('Update team details on invoice?', {
okTitle: 'Update',
cancelTitle: 'Dismiss',
cancelVariant: 'btn-link',
contentClass: 'bg-base dp--24',
});
if (confirmed) { */
this.$store.dispatch('invoices/prefillTeam', {
invoiceId: this.invoice.id,
});
/* } */
}
},
},
};
</script>

View File

@ -1,9 +1,7 @@
import storage from 'localforage';
import TeamService from '@/services/team.service';
import {
validate, generateInvoiceNumber, removeVuexORMFlags, uuidv4,
validate, removeVuexORMFlags,
} from '@/utils/helpers';
import dayjs from 'dayjs';
class InvoiceService {
async getInvoices() {
@ -17,40 +15,7 @@ class InvoiceService {
}
async createInvoice(invoice) {
const team = await TeamService.getTeam();
const invoices = await this.getInvoices();
invoice.issued_at = dayjs()
.format('YYYY-MM-DD');
invoice.due_at = dayjs()
.add(team.invoice_due_days || 14, 'days')
.format('YYYY-MM-DD');
invoice.number = generateInvoiceNumber(invoices);
invoice.late_fee = team.invoice_late_fee || 0.5;
invoice.from_name = team.company_name;
invoice.from_address = team.company_address;
invoice.from_postal_code = team.company_postal_code;
invoice.from_city = team.company_city;
invoice.from_country = team.company_country;
invoice.from_county = team.company_county;
invoice.from_website = team.website;
invoice.from_email = team.contact_email;
invoice.from_phone = team.contact_phone;
invoice.vat_rate = team.vat_rate || 0;
invoice.currency = team.currency || 'USD';
// Add custom fields
invoice.team_fields = team.fields.map(field => ({
id: uuidv4(),
label: field.label,
value: field.value,
invoice_id: invoice.id,
}));
delete invoice.client;
return this.saveInvoice(invoice);
}

View File

@ -15,7 +15,9 @@ export default {
},
async updateInvoiceClientField({ dispatch }, payload) {
await dispatch('invoiceClientFieldProps', payload);
return dispatch('invoices/updateInvoice', null, { root: true });
return dispatch('invoices/updateInvoice', {
invoiceId: payload.invoiceId,
}, { root: true });
},
async removeInvoiceClientFields(store, invoiceId) {
return InvoiceClientField.delete(field => field.invoice_id === invoiceId);

View File

@ -17,7 +17,9 @@ export default {
},
async updateInvoiceRow({ dispatch }, payload) {
await dispatch('invoiceRowProps', payload);
return dispatch('invoices/updateInvoice', null, { root: true });
return dispatch('invoices/updateInvoice', {
invoiceId: payload.invoiceId,
}, { root: true });
},
async addRow(store, invoiceId) {
const row = await InvoiceRow.createNew();

View File

@ -15,7 +15,9 @@ export default {
},
async updateInvoiceTeamField({ dispatch }, payload) {
await dispatch('invoiceTeamFieldProps', payload);
return dispatch('invoices/updateInvoice', null, { root: true });
return dispatch('invoices/updateInvoice', {
invoiceId: payload.invoiceId,
}, { root: true });
},
async addInvoiceTeamField(store, payload) {
const field = await InvoiceTeamField.createNew();
@ -24,8 +26,11 @@ export default {
invoice_id: payload.invoiceId,
});
},
async removeInvoiceTeamField(store, fieldId) {
await InvoiceTeamField.delete(fieldId);
async removeInvoiceTeamFields(store, invoiceId) {
return InvoiceTeamField.delete(field => field.invoice_id === invoiceId);
},
removeInvoiceTeamField(store, fieldId) {
return InvoiceTeamField.delete(fieldId);
},
},
};

View File

@ -1,9 +1,16 @@
import InvoiceService from '@/services/invoice.service';
import Invoice from '@/store/models/invoice';
import { pick } from '@/utils/helpers';
import { generateInvoiceNumber, pick } from '@/utils/helpers';
import dayjs from 'dayjs';
import Errors from '@/utils/errors';
function getInvoice(invoiceId) {
return Invoice.query()
.with(['client', 'client_fields', 'team_fields'])
.with('rows', query => query.orderBy('order', 'asc'))
.find(invoiceId);
}
export default {
namespaced: true,
state: {
@ -43,19 +50,22 @@ export default {
commit('invoiceId', invoiceId);
return invoice;
},
async createNewInvoice() {
async createNewInvoice({ dispatch }) {
const invoice = await Invoice.createNew();
await InvoiceService.createInvoice(invoice);
await dispatch('prefillTeam', {
invoiceId: invoice.id,
});
return invoice.id;
},
invoiceProps({ state }, props) {
invoiceProps(store, payload) {
return Invoice.update({
where: state.invoiceId,
data: props,
where: payload.invoiceId,
data: payload.props,
});
},
async updateClient({ getters, dispatch }, props) {
const clientProps = pick(props, {
async updateClient({ dispatch }, payload) {
const clientProps = pick(payload.props, {
bank_account_id: 'bank_account_id',
client_name: 'company_name',
client_address: 'company_address',
@ -66,19 +76,20 @@ export default {
client_email: 'invoice_email',
currency: 'currency',
});
if ('vat_rate' in props) {
clientProps.has_vat = props.vat_rate > 0;
if ('vat_rate' in payload.props) {
clientProps.has_vat = payload.props.vat_rate > 0;
}
const invoice = getInvoice(payload.invoiceId);
if (Object.keys(clientProps).length > 0 && getters.invoice.client_id) {
if (Object.keys(clientProps).length > 0 && invoice.client_id) {
dispatch('clients/updateClientById', {
props: clientProps,
clientId: getters.invoice.client_id,
clientId: invoice.client_id,
}, { root: true });
}
},
async updateTeam({ getters, dispatch }, props) {
const teamProps = pick(props, {
async updateTeam({ dispatch }, payload) {
const teamProps = pick(payload.props, {
late_fee: 'invoice_late_fee',
from_name: 'company_name',
from_address: 'company_address',
@ -91,11 +102,13 @@ export default {
from_phone: 'contact_phone',
vat_rate: 'vat_rate',
});
if ('due_at' in props || 'issued_at' in props) {
teamProps.invoice_due_days = dayjs(getters.invoice.due_at)
.diff(getters.invoice.issued_at, 'days');
const invoice = getInvoice(payload.invoiceId);
if ('due_at' in payload.props || 'issued_at' in payload.props) {
teamProps.invoice_due_days = dayjs(invoice.due_at)
.diff(invoice.issued_at, 'days');
}
if ('vat_rate' in props) {
if ('vat_rate' in payload.props) {
// You can only set VAT to 0 if setting it directly under settings
// This is to avoid setting general VAT to 0, if only changing per invoice
if (parseFloat(teamProps.vat_rate) === 0) {
@ -107,15 +120,15 @@ export default {
dispatch('teams/updateTeam', teamProps, { root: true });
}
},
async updateInvoice({ dispatch, commit, getters }, props) {
if (props) {
await dispatch('invoiceProps', props);
await dispatch('updateClient', props);
await dispatch('updateTeam', props);
async updateInvoice({ dispatch, commit }, payload) {
if (payload.props) {
await dispatch('invoiceProps', payload);
await dispatch('updateClient', payload);
await dispatch('updateTeam', payload);
}
commit('clearErrors');
return InvoiceService.updateInvoice(getters.invoice)
return InvoiceService.updateInvoice(getInvoice(payload.invoiceId))
.catch(err => commit('setErrors', err.errors));
},
async deleteInvoice(store, invoice) {
@ -135,11 +148,11 @@ export default {
},
prefillClient({ dispatch, rootGetters }, payload) {
const client = payload.client;
dispatch('invoiceClientFields/removeInvoiceClientFields', payload.invoice.id, { root: true });
dispatch('invoiceClientFields/removeInvoiceClientFields', payload.invoiceId, { root: true });
client.fields.forEach((field) => {
dispatch('invoiceClientFields/addInvoiceClientField', {
invoiceId: payload.invoice.id,
invoiceId: payload.invoiceId,
props: {
label: field.label,
value: field.value,
@ -149,27 +162,65 @@ export default {
});
return dispatch('updateInvoice', {
client_id: client.id,
client_name: client.company_name,
client_address: client.company_address,
client_postal_code: client.company_postal_code,
client_city: client.company_city,
client_county: client.company_county,
client_country: client.company_country,
client_email: client.invoice_email,
currency: client.currency || rootGetters['teams/team'].currency || 'USD',
vat_rate: client.has_vat ? rootGetters['teams/team'].vat_rate : 0,
bank_name: client.bank_account ? client.bank_account.bank_name : null,
bank_account_no: client.bank_account ? client.bank_account.account_no : null,
invoiceId: payload.invoiceId,
props: {
client_id: client.id,
client_name: client.company_name,
client_address: client.company_address,
client_postal_code: client.company_postal_code,
client_city: client.company_city,
client_county: client.company_county,
client_country: client.company_country,
client_email: client.invoice_email,
currency: client.currency || rootGetters['teams/team'].currency || 'USD',
vat_rate: client.has_vat ? rootGetters['teams/team'].vat_rate : 0,
bank_name: client.bank_account ? client.bank_account.bank_name : null,
bank_account_no: client.bank_account ? client.bank_account.account_no : null,
},
});
},
prefillTeam({ dispatch, getters, rootGetters }, payload) {
const team = rootGetters['teams/team'];
dispatch('invoiceTeamFields/removeInvoiceTeamFields', payload.invoiceId, { root: true });
team.fields.forEach((field) => {
dispatch('invoiceTeamFields/addInvoiceTeamField', {
invoiceId: payload.invoiceId,
props: {
label: field.label,
value: field.value,
},
}, { root: true });
});
return dispatch('updateInvoice', {
invoiceId: payload.invoiceId,
props: {
issued_at: dayjs()
.format('YYYY-MM-DD'),
due_at: dayjs()
.add(team.invoice_due_days || 14, 'days')
.format('YYYY-MM-DD'),
number: generateInvoiceNumber(getters.all),
late_fee: team.invoice_late_fee || 0.5,
from_name: team.company_name,
from_address: team.company_address,
from_postal_code: team.company_postal_code,
from_city: team.company_city,
from_country: team.company_country,
from_county: team.company_county,
from_website: team.website,
from_email: team.contact_email,
from_phone: team.contact_phone,
vat_rate: team.vat_rate || 0,
currency: team.currency || 'USD',
},
});
},
},
getters: {
invoice(state) {
return Invoice.query()
.with(['client', 'client_fields', 'team_fields'])
.with('rows', query => query.orderBy('order', 'asc'))
.find(state.invoiceId);
return getInvoice(state.invoiceId);
},
all() {
return Invoice.query()