2
0
mirror of https://github.com/frappe/books.git synced 2025-02-02 20:18:26 +00:00

feat: Use InvoiceForm for PurchaseInvoice as well

- Button with icon prop
This commit is contained in:
Faris Ansari 2019-10-14 02:49:28 +05:30
parent 1537ea4609
commit bd5d812d77
13 changed files with 80 additions and 42 deletions

View File

@ -26,7 +26,7 @@ module.exports = {
getFilters: (query, doc) => { getFilters: (query, doc) => {
return { return {
isGroup: 0, isGroup: 0,
accountType: doc.customer === 1 ? 'Receivable' : 'Payable' accountType: doc.customer ? 'Receivable' : 'Payable'
}; };
} }
}, },

View File

@ -17,7 +17,7 @@ module.exports = {
fieldname: 'date', fieldname: 'date',
label: 'Date', label: 'Date',
fieldtype: 'Date', fieldtype: 'Date',
defaultValue: new Date().toISOString() default: new Date().toISOString().slice(0, 10)
}, },
{ {
fieldname: 'supplier', fieldname: 'supplier',

View File

@ -4,6 +4,7 @@ import indicators from 'frappejs/ui/constants/indicators';
export default { export default {
doctype: 'PurchaseInvoice', doctype: 'PurchaseInvoice',
title: _('Purchase Invoice'), title: _('Purchase Invoice'),
formRoute: name => `/edit/PurchaseInvoice/${name}`,
columns: [ columns: [
'supplier', 'supplier',
{ {

View File

@ -45,7 +45,7 @@ module.exports = class PurchaseInvoiceServer extends PurchaseInvoice {
await entries.validateEntries(); await entries.validateEntries();
} }
async afterSubmit() { async beforeSubmit() {
const entries = await this.getPosting(); const entries = await this.getPosting();
await entries.post(); await entries.post();
await frappe.db.setValue( await frappe.db.setValue(

View File

@ -6,6 +6,13 @@ module.exports = {
isChild: 1, isChild: 1,
keywordFields: [], keywordFields: [],
layout: 'ratio', layout: 'ratio',
tableFields: [
'item',
'tax',
'quantity',
'rate',
'amount'
],
fields: [ fields: [
{ {
fieldname: 'item', fieldname: 'item',

View File

@ -20,7 +20,7 @@ module.exports = {
fieldname: 'date', fieldname: 'date',
label: 'Date', label: 'Date',
fieldtype: 'Date', fieldtype: 'Date',
defaultValue: new Date().toISOString() default: new Date().toISOString().slice(0, 10)
}, },
{ {
fieldname: 'customer', fieldname: 'customer',

View File

@ -57,7 +57,7 @@ module.exports = class SalesInvoiceServer extends SalesInvoice {
await entries.validateEntries(); await entries.validateEntries();
} }
async afterSubmit() { async beforeSubmit() {
const entries = await this.getPosting(); const entries = await this.getPosting();
await entries.post(); await entries.post();
await frappe.db.setValue( await frappe.db.setValue(

View File

@ -1,6 +1,6 @@
<template> <template>
<button <button
class="px-4 py-2 focus:outline-none rounded-6px" class="focus:outline-none rounded-6px"
:style="style" :style="style"
v-bind="$attrs" v-bind="$attrs"
v-on="$listeners" v-on="$listeners"
@ -15,11 +15,16 @@ export default {
type: { type: {
type: String, type: String,
default: 'secondary' default: 'secondary'
},
icon: {
type: Boolean,
default: false
} }
}, },
computed: { computed: {
style() { style() {
return { return {
padding: this.icon ? '9px 15px' : '6px 24px',
'background-image': 'background-image':
this.type === 'primary' this.type === 'primary'
? 'linear-gradient(180deg, #4AC3F8 0%, #2490EF 100%)' ? 'linear-gradient(180deg, #4AC3F8 0%, #2490EF 100%)'

View File

@ -2,7 +2,7 @@
<div class="flex"> <div class="flex">
<Sidebar class="w-56" /> <Sidebar class="w-56" />
<div class="flex flex-1 overflow-y-hidden bg-white"> <div class="flex flex-1 overflow-y-hidden bg-white">
<keep-alive exclude="ListView"> <keep-alive include="InvoiceForm">
<router-view class="flex-1" :key="$route.fullPath" /> <router-view class="flex-1" :key="$route.fullPath" />
</keep-alive> </keep-alive>
<div class="flex" v-if="$route.query.edit && $route.query.doctype && $route.query.name"> <div class="flex" v-if="$route.query.edit && $route.query.doctype && $route.query.name">

View File

@ -3,11 +3,26 @@
<PageHeader> <PageHeader>
<a class="cursor-pointer font-semibold" slot="title" @click="$router.go(-1)">{{ _('Back') }}</a> <a class="cursor-pointer font-semibold" slot="title" @click="$router.go(-1)">{{ _('Back') }}</a>
<template slot="actions"> <template slot="actions">
<Button class="text-gray-900 text-xs">Customise</Button> <Button class="text-gray-900 text-xs">{{ _('Customise') }}</Button>
<Button v-if="doc._notInserted || doc._dirty" type="primary" class="text-white text-xs ml-2" @click="onSaveClick">{{ _('Save') }}</Button> <Button
v-if="doc._notInserted || doc._dirty"
type="primary"
class="text-white text-xs ml-2"
@click="onSaveClick"
>{{ _('Save') }}</Button>
<Button
v-if="!doc._dirty && !doc._notInserted && !doc.submitted"
type="primary"
class="text-white text-xs ml-2"
@click="onSubmitClick"
>{{ _('Submit') }}</Button>
</template> </template>
</PageHeader> </PageHeader>
<div class="flex justify-center flex-1 mb-8 mt-6" v-if="meta"> <div
class="flex justify-center flex-1 mb-8 mt-6"
v-if="meta"
:class="doc.submitted && 'pointer-events-none'"
>
<div class="border rounded shadow h-full flex flex-col justify-between" style="width: 600px"> <div class="border rounded shadow h-full flex flex-col justify-between" style="width: 600px">
<div> <div>
<div class="px-6 pt-6"> <div class="px-6 pt-6">
@ -53,11 +68,11 @@
</div> </div>
<div class="w-1/3"> <div class="w-1/3">
<FormControl <FormControl
:df="meta.getField('customer')" :df="meta.getField(partyField.fieldname)"
:value="doc.customer" :value="doc[partyField.fieldname]"
:placeholder="'Customer'" :placeholder="partyField.label"
@change="value => doc.set('customer', value)" @change="value => doc.set(partyField.fieldname, value)"
@new-doc="doc => doc.set('customer', doc.name)" @new-doc="doc => doc.set(partyField.fieldname, doc.name)"
input-class="bg-gray-100 rounded-lg p-2 text-right" input-class="bg-gray-100 rounded-lg p-2 text-right"
/> />
<div <div
@ -86,7 +101,9 @@
<div>{{ tax.account }} ({{ tax.rate }}%)</div> <div>{{ tax.account }} ({{ tax.rate }}%)</div>
<div>{{ tax.amount }}</div> <div>{{ tax.amount }}</div>
</div> </div>
<div class="flex pl-2 justify-between py-3 border-t text-green-600 font-semibold text-base"> <div
class="flex pl-2 justify-between py-3 border-t text-green-600 font-semibold text-base"
>
<div>Grand Total</div> <div>Grand Total</div>
<div>{{ doc.grandTotal }}</div> <div>{{ doc.grandTotal }}</div>
</div> </div>
@ -105,7 +122,7 @@ import AddIcon from '@/components/Icons/Add';
export default { export default {
name: 'InvoiceForm', name: 'InvoiceForm',
props: ['name'], props: ['doctype', 'name'],
components: { components: {
PageHeader, PageHeader,
Button, Button,
@ -115,7 +132,7 @@ export default {
}, },
provide() { provide() {
return { return {
doctype: 'SalesInvoice', doctype: this.doctype,
name: this.name name: this.name
}; };
}, },
@ -134,12 +151,19 @@ export default {
}, },
itemTableColumnRatio() { itemTableColumnRatio() {
return [0.3].concat(this.itemTableFields.map(_ => 1)); return [0.3].concat(this.itemTableFields.map(_ => 1));
} },
partyField() {
let fieldname = {
SalesInvoice: 'customer',
PurchaseInvoice: 'supplier'
}[this.doctype];
return this.meta.getField(fieldname);
},
}, },
async mounted() { async mounted() {
this.meta = frappe.getMeta('SalesInvoice'); this.meta = frappe.getMeta(this.doctype);
this.itemsMeta = frappe.getMeta('SalesInvoiceItem'); this.itemsMeta = frappe.getMeta(`${this.doctype}Item`);
this.doc = await frappe.getDoc('SalesInvoice', this.name); this.doc = await frappe.getDoc(this.doctype, this.name);
window.si = this.doc; window.si = this.doc;
}, },
methods: { methods: {
@ -154,6 +178,9 @@ export default {
} else { } else {
this.doc.update(); this.doc.update();
} }
},
async onSubmitClick() {
await this.doc.submit();
} }
} }
}; };

View File

@ -26,7 +26,7 @@
</Row> </Row>
</div> </div>
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
<Button :class="start == 0 && 'text-gray-600'" :disabled="start == 0" @click="prevPage"> <Button :icon="true" :class="start == 0 && 'text-gray-600'" :disabled="start == 0" @click="prevPage">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@ -45,7 +45,7 @@
<span class="text-gray-600">of</span> <span class="text-gray-600">of</span>
<span class="font-medium">{{ totalCount }}</span> <span class="font-medium">{{ totalCount }}</span>
</div> </div>
<Button :class="start + pageLength >= totalCount && 'text-gray-600'" :disabled="start + pageLength >= totalCount" @click="nextPage"> <Button :icon="true" :class="start + pageLength >= totalCount && 'text-gray-600'" :disabled="start + pageLength >= totalCount" @click="nextPage">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"

View File

@ -1,10 +1,9 @@
<template> <template>
<div class="flex"> <div class="flex flex-col">
<div class="flex flex-col flex-1">
<PageHeader> <PageHeader>
<h1 slot="title" class="text-xl font-bold" v-if="title">{{ title }}</h1> <h1 slot="title" class="text-xl font-bold" v-if="title">{{ title }}</h1>
<template slot="actions"> <template slot="actions">
<Button type="primary" @click="makeNewDoc"> <Button :icon="true" type="primary" @click="makeNewDoc">
<Add class="w-3 h-3 stroke-current text-white" /> <Add class="w-3 h-3 stroke-current text-white" />
</Button> </Button>
<SearchBar class="ml-2" /> <SearchBar class="ml-2" />
@ -14,7 +13,6 @@
<List :listConfig="listConfig" :filters="filters" class="flex-1" /> <List :listConfig="listConfig" :filters="filters" class="flex-1" />
</div> </div>
</div> </div>
</div>
</template> </template>
<script> <script>
import frappe from 'frappejs'; import frappe from 'frappejs';
@ -80,7 +78,7 @@ export default {
title: this.doctype, title: this.doctype,
doctype: this.doctype, doctype: this.doctype,
columns: frappe.getMeta(this.doctype).getKeywordFields() columns: frappe.getMeta(this.doctype).getKeywordFields()
} };
} }
}, },
title() { title() {

View File

@ -1,14 +1,14 @@
<template> <template>
<div class="border-l h-full"> <div class="border-l h-full">
<div class="flex justify-end px-4 pt-4"> <div class="flex justify-end px-4 pt-4">
<Button @click="routeToList"> <Button :icon="true" @click="routeToList">
<XIcon class="w-3 h-3 stroke-current text-gray-700" /> <XIcon class="w-3 h-3 stroke-current text-gray-700" />
</Button> </Button>
<Button @click="insertDoc" type="primary" v-if="doc._notInserted" class="ml-2 flex"> <Button :icon="true" @click="insertDoc" type="primary" v-if="doc._notInserted" class="ml-2 flex">
<feather-icon name="check" class="text-white" /> <feather-icon name="check" class="text-white" />
</Button> </Button>
</div> </div>
<div class="px-1 pt-2 pb-4 border-b flex items-center justify-between"> <div class="pl-1 pr-4 pt-2 pb-4 border-b flex items-center justify-between">
<FormControl <FormControl
ref="titleControl" ref="titleControl"
v-if="titleDocField" v-if="titleDocField"