fix: assign contacts customer/vendor in make jorunal.

This commit is contained in:
a.bouhuolia
2021-04-19 18:14:43 +02:00
parent fbe39b8e9d
commit 537150b222
8 changed files with 52 additions and 36 deletions

View File

@@ -51,6 +51,7 @@ export default function ContactsSuggestField({
<MenuItem
key={contact.id}
text={contact.display_name}
label={contact.formatted_contact_service}
onClick={handleClick}
/>
),

View File

@@ -12,10 +12,7 @@ export default function ContactsListCellRenderer({
}) {
const handleContactSelected = useCallback(
(contact) => {
updateData(index, id, {
contact_id: contact.id,
contact_type: contact.contact_type,
});
updateData(index, 'contact_id', contact.id);
},
[updateData, index, id],
);

View File

@@ -25,7 +25,7 @@ export default function MakeJournalEntriesTable({
minLinesNumber = 4,
currencyCode,
}) {
const { accounts, customers } = useMakeJournalFormContext();
const { accounts, contacts } = useMakeJournalFormContext();
// Memorized data table columns.
const columns = useJournalTableEntriesColumns();
@@ -68,10 +68,7 @@ export default function MakeJournalEntriesTable({
errors: error,
updateData: handleUpdateData,
removeRow: handleRemoveRow,
contacts: customers.map((customer) => ({
...customer,
contact_type: 'customer',
})),
contacts,
autoFocus: ['account_id', 0],
currencyCode,
}}

View File

@@ -2,7 +2,7 @@ import React, { createContext, useState } from 'react';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import {
useAccounts,
useCustomers,
useAutoCompleteContacts,
useCurrencies,
useJournal,
useCreateJournal,
@@ -21,9 +21,9 @@ function MakeJournalProvider({ journalId, ...props }) {
// Load the customers list.
const {
data: { customers },
isLoading: isCustomersLoading,
} = useCustomers();
data: contacts,
isLoading: isContactsLoading,
} = useAutoCompleteContacts();
// Load the currencies list.
const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
@@ -47,7 +47,7 @@ function MakeJournalProvider({ journalId, ...props }) {
const provider = {
accounts,
customers,
contacts,
currencies,
manualJournal,
@@ -55,7 +55,7 @@ function MakeJournalProvider({ journalId, ...props }) {
editJournalMutate,
isAccountsLoading,
isCustomersLoading,
isContactsLoading,
isCurrenciesLoading,
isJournalLoading,
isSettingsLoading,
@@ -72,7 +72,7 @@ function MakeJournalProvider({ journalId, ...props }) {
isJournalLoading ||
isAccountsLoading ||
isCurrenciesLoading ||
isCustomersLoading ||
isContactsLoading ||
isSettingsLoading
}
name={'make-journal-page'}

View File

@@ -128,7 +128,6 @@ export default class ManualJournalsController extends BaseController {
.optional({ nullable: true })
.isInt({ max: DATATYPES_LENGTH.INT_10 })
.toInt(),
check('entries.*.contact_type').optional().isIn(['vendor', 'customer']),
];
}

View File

@@ -6,7 +6,6 @@ exports.up = function(knex) {
table.decimal('debit', 13, 3);
table.integer('index').unsigned();
table.integer('account_id').unsigned().index().references('id').inTable('accounts');
table.string('contact_type').nullable().index();
table.integer('contact_id').unsigned().nullable().index();
table.string('note');
table.integer('manual_journal_id').unsigned().index().references('id').inTable('manual_journals');

View File

@@ -25,7 +25,6 @@ export interface IManualJournalEntry {
accountId: number;
note: string;
contactId?: number;
contactType?: string;
}
export interface IManualJournalEntryDTO {
@@ -35,7 +34,6 @@ export interface IManualJournalEntryDTO {
accountId: number;
note: string;
contactId?: number;
contactType?: string;
}
export interface IManualJournalDTO {

View File

@@ -1,7 +1,7 @@
import { difference, sumBy, omit, map } from 'lodash';
import { Service, Inject } from 'typedi';
import moment from 'moment';
import { ServiceError } from 'exceptions';
import { ServiceError, ServiceErrors } from 'exceptions';
import {
IManualJournalDTO,
IManualJournalsService,
@@ -187,15 +187,27 @@ export default class ManualJournalsService implements IManualJournalsService {
private async validateAccountWithContactType(
tenantId: number,
entriesDTO: IManualJournalEntry[],
accountBySlug: string,
contactType: string
): Promise<void> {
const { Account, Contact } = this.tenancy.models(tenantId);
): Promise<void | ServiceError> {
const { Account } = this.tenancy.models(tenantId);
const { contactRepository } = this.tenancy.repositories(tenantId);
// Retrieve account meta by the given account slug.
const account = await Account.query().findOne('slug', accountBySlug);
// Retrieve all stored contacts on the storage from contacts entries.
const storedContacts = await contactRepository.findWhereIn(
'id',
entriesDTO
.filter((entry) => entry.contactId)
.map((entry) => entry.contactId)
);
// Converts the stored contacts to map with id as key and entry as value.
const storedContactsMap = new Map(
storedContacts.map((contact) => [contact.id, contact])
);
// Filter all entries of the given account.
const accountEntries = entriesDTO.filter(
(entry) => entry.accountId === account.id
@@ -205,14 +217,15 @@ export default class ManualJournalsService implements IManualJournalsService {
return;
}
// Filter entries that have no contact type or not equal the valid type.
const entriesNoContact = accountEntries.filter(
(entry) => !entry.contactType || entry.contactType !== contactType
);
const entriesNoContact = accountEntries.filter((entry) => {
const contact = storedContactsMap.get(entry.contactId);
return !contact || contact.contactService !== contactType;
});
// Throw error in case one of entries that has invalid contact type.
if (entriesNoContact.length > 0) {
const indexes = entriesNoContact.map((e) => e.index);
throw new ServiceError(ERRORS.ENTRIES_SHOULD_ASSIGN_WITH_CONTACT, '', {
return new ServiceError(ERRORS.ENTRIES_SHOULD_ASSIGN_WITH_CONTACT, '', {
accountSlug: accountBySlug,
contactType,
indexes,
@@ -242,11 +255,25 @@ export default class ManualJournalsService implements IManualJournalsService {
'accounts-payable',
'vendor'
),
]);
]).then((results) => {
const metadataErrors = results
.filter((result) => result instanceof ServiceError)
.map((result: ServiceError) => result.payload);
if (metadataErrors.length > 0) {
throw new ServiceError(
ERRORS.ENTRIES_SHOULD_ASSIGN_WITH_CONTACT,
'',
metadataErrors
);
}
return results;
});
}
/**
* Vaplidate entries contacts existance.
* Validate entries contacts existance.
* @param {number} tenantId -
* @param {IManualJournalDTO} manualJournalDTO
*/
@@ -280,10 +307,7 @@ export default class ManualJournalsService implements IManualJournalsService {
const storedContact = storedContactsMap.get(contactEntry.contactId);
// in case the contact id not found.
if (
!storedContact ||
storedContact.contactService !== contactEntry.contactType
) {
if (!storedContact) {
notFoundContactsIds.push(storedContact);
}
});
@@ -347,7 +371,8 @@ export default class ManualJournalsService implements IManualJournalsService {
// Settings tenant service.
const settings = this.tenancy.settings(tenantId);
const currencyCode = settings.get({
group: 'organization', key: 'base_currency',
group: 'organization',
key: 'base_currency',
});
// Validate manual journal number require.
this.validateJournalNoRequire(journalNumber);
@@ -803,7 +828,7 @@ export default class ManualJournalsService implements IManualJournalsService {
return manualJournal;
}
/**
* Reverts the manual journal journal entries.
* @param {number} tenantId