Skip to content

Commit 38f3bf0

Browse files
authored
Merge pull request #330 from joriswijnant/issue-191-split-inbound
Issue 191 split inbound
2 parents 5f31a3f + d404dc8 commit 38f3bf0

File tree

9 files changed

+78
-30
lines changed

9 files changed

+78
-30
lines changed

frontend/src/components/invoice/controls/InvoiceCreditNotas.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ export const InvoiceCreditNotas = ({ model, onChange}: InvoiceCreditNotasProps)
5656
'buttons'
5757
],
5858
buttons: ['comment', 'edit', 'validate', 'preview'],
59-
currentInvoice: model
59+
currentInvoice: model,
60+
defaultSorter: (a, b) => a.number - b.number
6061
});
6162

62-
feature.list.sorter = (a, b) => a.number - b.number;
6363

6464
const saveCreditNotas = (selectedInvoices: ListSelectionItem<InvoiceModel>) => {
6565
if(Array.isArray(selectedInvoices)) {

frontend/src/components/invoice/models/getInvoiceFeature.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export type InvoiceFeatureBuilderConfig = IFeatureBuilderConfig<InvoiceModel, Li
2626
disableFilters?: boolean;
2727
invoicesTotalOnly?: boolean;
2828
buttons?: InvoiceListRowAction[];
29-
currentInvoice?: InvoiceModel
29+
currentInvoice?: InvoiceModel,
30+
defaultSorter?: (a: InvoiceModel, b: InvoiceModel) => number
3031
};
3132

3233
export interface IInvoiceListData {
@@ -100,7 +101,7 @@ export function createInvoiceList(config: InvoiceFeatureBuilderConfig): IFeature
100101
list: {
101102
rows: listRows,
102103
data: config.data,
103-
sorter: (a, b) => b.number - a.number,
104+
sorter: config.defaultSorter ?? ( (a, b) => b.number - a.number ),
104105
filter: !config.disableFilters ? {
105106
fullTextSearch: searchInvoices,
106107
updateFilter: config.setFilters,

frontend/src/components/invoice/models/getNewInvoice.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import InvoiceModel from './InvoiceModel';
33
import {ConfigModel} from '../../config/models/ConfigModel';
44
import {ClientModel} from '../../client/models/ClientModels';
5-
import {getInvoiceDate, today} from './invoice-date-strategy';
5+
import {today} from './invoice-date-strategy';
66

77

88
export type NewInvoiceType = Partial<Omit<InvoiceModel, '_id'>> & {
@@ -70,7 +70,7 @@ export const getNewClonedInvoice = (
7070

7171
return getNewInvoice(invoiceBlueprint.config, invoices, [], {
7272
...invoiceBlueprint,
73-
lines: invoiceToCopy.lines.map(line => ({...line, amount: 0, audit: {} })),
73+
lines: invoiceToCopy.lines.map(line => ({...line, amount: line.amount*-1, audit: {} })),
7474
creditNotas: [...invoiceBlueprint.creditNotas, invoiceBlueprint.number],
7575
note: '',
7676
comments: []

frontend/src/components/project/models/ProjectMonthModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface ProjectMonthModel {
2323
orderNr: string;
2424
audit: IAudit;
2525
verified: ProjectMonthStatus;
26+
verifiedInvoices: number[];
2627
attachments: Attachment[];
2728
}
2829

frontend/src/components/project/models/getNewProject.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const getNewProjectMonth = (): ProjectMonthModel => ({
4848
comments: [],
4949
orderNr: '',
5050
verified: false,
51+
verifiedInvoices: [],
5152
attachments: [],
5253
audit: {} as IAudit,
5354
});

frontend/src/components/project/models/getProjectMonthFeature.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {ProjectMonthTimesheetCell} from '../project-month-list/table/ProjectMont
88
import {ProjectMonthConsultantCell} from '../project-month-list/table/ProjectMonthConsultantCell';
99
import {ProjectMonthInboundCell} from '../project-month-list/table/inbound/ProjectMonthInboundCell';
1010
import {ProjectMonthOutboundCell} from '../project-month-list/table/outbound/ProjectMonthOutboundCell';
11-
import {getInvoiceDueDateVariant} from '../../invoice/invoice-table/getInvoiceListRowClass';
1211
import {ProjectMonthNotesCell} from '../project-month-list/table/ProjectMonthNotesCell';
1312
import {ConsultantCountFooter} from '../project-month-list/table/footers/ConsultantCountFooter';
1413
import { ProjectClientForecastFooter } from "../project-month-list/table/footers/ProjectClientForecastFooter";
@@ -69,7 +68,7 @@ const projectListConfig = (config: ProjectMonthFeatureBuilderConfig): IList<Full
6968
key: 'project',
7069
value: p => <ProjectMonthConsultantCell fullProjectMonth={p} />,
7170
className: p => {
72-
if (p.details.verified || p.invoice?.verified) {
71+
if (p.details.verified) {
7372
return 'validated';
7473
}
7574
return undefined;
@@ -127,10 +126,9 @@ const projectListConfig = (config: ProjectMonthFeatureBuilderConfig): IList<Full
127126
value: p => <ProjectMonthOutboundCell fullProjectMonth={p} />,
128127
className: p => {
129128
if (p.invoice) {
130-
if (p.invoice.verified) {
129+
if (p.details.verified) {
131130
return 'validated';
132131
}
133-
return `table-${getInvoiceDueDateVariant(p.invoice)}`;
134132
}
135133
return undefined;
136134
},
@@ -145,7 +143,7 @@ const projectListConfig = (config: ProjectMonthFeatureBuilderConfig): IList<Full
145143
key: 'notes',
146144
value: p => <ProjectMonthNotesCell fullProjectMonth={p} />,
147145
className: p => {
148-
if (p.details.verified || p.invoice?.verified) {
146+
if (p.details.verified) {
149147
return 'validated';
150148
}
151149
return undefined;

frontend/src/components/project/project-month-list/table/inbound/InboundAmountForecast.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ export const InboundAmountForecast = ({ fullProjectMonth, includeTax = true }: I
4444
let amount = timesheetConfig.amount;
4545
if (includeTax &&
4646
(!fullProjectMonth.partner || !fullProjectMonth.partner.country?.trim() || belgiums.includes(fullProjectMonth.partner.country))) {
47-
const temp = amount
4847
amount *= (1 + tax / 100);
4948
}
5049

frontend/src/components/project/project-month-list/table/outbound/OutboundInvoice.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,35 @@
1-
import { FullProjectMonthModel } from '../../../models/FullProjectMonthModel';
21
import { moneyFormat, formatDate } from '../../../../utils';
32
import { InvoiceNumberCell } from '../../../../invoice/invoice-table/InvoiceNumberCell';
43
import { InvoiceListRowActions } from '../../../../invoice/invoice-table/InvoiceListRowActions';
54
import { InvoiceEmail } from './InvoiceEmail';
5+
import InvoiceModel from '../../../../invoice/models/InvoiceModel';
6+
import { CSSProperties } from 'react';
67

78
interface OutboundInvoiceProps {
8-
fullProjectMonth: FullProjectMonthModel;
9+
invoice: InvoiceModel;
910
toggleValid: (valid: boolean) => void;
11+
className?: string;
12+
style?: CSSProperties
1013
}
1114

1215

13-
export const OutboundInvoice = ({ fullProjectMonth, toggleValid }: OutboundInvoiceProps) => {
14-
if (!fullProjectMonth.invoice) {
15-
return null;
16-
}
16+
export const OutboundInvoice = ({ invoice, toggleValid, className, style }: OutboundInvoiceProps) => {
17+
1718

1819
return (
19-
<div className="outbound-invoice-cell">
20+
<div className={`outbound-invoice-cell ${className || ''}`} style={style}>
2021
<div>
21-
<span style={{ whiteSpace: 'nowrap' }}>{moneyFormat(fullProjectMonth.invoice.money.total)}</span>
22+
<span style={{ whiteSpace: 'nowrap' }}>{moneyFormat(invoice.money.total)}</span>
2223
<span>
23-
<InvoiceNumberCell invoice={fullProjectMonth.invoice} />
24-
&nbsp;({formatDate(fullProjectMonth.invoice.date, 'D/M')})
24+
<InvoiceNumberCell invoice={invoice} />
25+
&nbsp;({formatDate(invoice.date, 'D/M')})
2526
</span>
2627
</div>
2728
<div className="email">
28-
<InvoiceEmail invoice={fullProjectMonth.invoice} />
29+
<InvoiceEmail invoice={invoice} />
2930
</div>
3031
<div className="icons-cell">
31-
<InvoiceListRowActions invoice={fullProjectMonth.invoice} toggleValid={toggleValid} small buttons={['validate', 'preview']} />
32+
<InvoiceListRowActions invoice={invoice} toggleValid={toggleValid} small buttons={['validate', 'preview']} />
3233
</div>
3334
</div>
3435
);

frontend/src/components/project/project-month-list/table/outbound/ProjectMonthOutboundCell.tsx

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import {useDebouncedSave} from '../../../../hooks/useDebounce';
88
import { CreateInvoiceButton } from './CreateInvoiceButton';
99
import { OutboundInvoice } from './OutboundInvoice';
1010
import { Claim } from '../../../../users/models/UserModel';
11+
import { useSelector } from 'react-redux';
12+
import { ConfacState } from '../../../../../reducers/app-state';
13+
import InvoiceModel from '../../../../invoice/models/InvoiceModel';
14+
import { getInvoiceDueDateVariant } from '../../../../invoice/invoice-table/getInvoiceListRowClass';
1115

1216

1317
interface ProjectMonthOutboundCellProps {
@@ -18,19 +22,39 @@ interface ProjectMonthOutboundCellProps {
1822
/** Outbound form cell for a ProjectMonth row */
1923
export const ProjectMonthOutboundCell = ({fullProjectMonth}: ProjectMonthOutboundCellProps) => {
2024
const dispatch = useDispatch();
25+
const invoices = useSelector((state: ConfacState) => state.invoices)
2126

2227
const dispatcher = (orderNr: string) => {
2328
dispatch(patchProjectsMonth({...fullProjectMonth.details, orderNr}) as any);
2429
};
2530
const [orderNr, setOrderNr/* , saveOrderNr */] = useDebouncedSave<string>(fullProjectMonth.details.orderNr || '', dispatcher);
2631

2732

28-
const toggleValid = (verified: boolean | 'forced') => {
29-
dispatch(patchProjectsMonth({...fullProjectMonth.details, verified}) as any);
33+
const toggleValid = (verified: boolean | 'forced', invoice?: InvoiceModel) => {
34+
if(!invoice) {
35+
dispatch(patchProjectsMonth({...fullProjectMonth.details, verified}) as any);
36+
}
37+
38+
if(verified === 'forced'){
39+
dispatch(patchProjectsMonth({...fullProjectMonth.details, verified}) as any);
40+
}
41+
42+
if(verified)
43+
{
44+
dispatch(patchProjectsMonth({
45+
...fullProjectMonth.details,
46+
verified: invoice!.creditNotas.every(invoiceNbr => fullProjectMonth.details.verifiedInvoices.includes(invoiceNbr)),
47+
verifiedInvoices: [...fullProjectMonth.details.verifiedInvoices, invoice!.number]
48+
}) as any);
49+
} else {
50+
dispatch(patchProjectsMonth({
51+
...fullProjectMonth.details,
52+
verified,
53+
verifiedInvoices: fullProjectMonth.details.verifiedInvoices.filter(n => n !== invoice!.number)
54+
}) as any);
55+
}
3056
};
3157

32-
33-
3458
const ValidityToggle = (
3559
<ValidityToggleButton
3660
claim={Claim.ValidateProjectMonth}
@@ -82,8 +106,31 @@ export const ProjectMonthOutboundCell = ({fullProjectMonth}: ProjectMonthOutboun
82106
}
83107

84108

109+
const invoiceList = [
110+
...fullProjectMonth.invoice.creditNotas,
111+
fullProjectMonth.invoice.number
112+
]
85113

86114
return (
87-
<OutboundInvoice fullProjectMonth={fullProjectMonth} toggleValid={toggleValid} />
88-
);
115+
<>
116+
{invoiceList
117+
.sort((a, b) => a - b)
118+
.map(nbr => invoices.find(i => !i.isQuotation && i.number === nbr))
119+
.filter(i => i !== undefined)
120+
.map(i => (
121+
<OutboundInvoice
122+
key={i!.number}
123+
invoice={i!}
124+
toggleValid={(valid) => toggleValid(valid, i!)}
125+
className={
126+
fullProjectMonth.details.verifiedInvoices.includes(i!.number) ?
127+
'validated' :
128+
`table-${getInvoiceDueDateVariant(i!)}`
129+
}
130+
style={{backgroundColor: !fullProjectMonth.details.verifiedInvoices.includes(i!.number) ? 'var(--bs-table-bg)' : undefined}}
131+
/>
132+
))
133+
}
134+
</>
135+
)
89136
};

0 commit comments

Comments
 (0)