mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-25 00:59:50 +00:00
Compare commits
11 Commits
v0.24.12
...
fix/organi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f35e85c3d2 | ||
|
|
29decf9c5a | ||
|
|
f149ff43b4 | ||
|
|
fb05af8c00 | ||
|
|
688b1bfb56 | ||
|
|
0f8147daff | ||
|
|
96b24d4fb9 | ||
|
|
2a87103bc8 | ||
|
|
238b60144f | ||
|
|
fcee85e358 | ||
|
|
75b98c39d8 |
@@ -1,5 +1,5 @@
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
import bluebird from 'bluebird';
|
||||
import * as bluebird from 'bluebird';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
validateLinkModelEntryExists,
|
||||
@@ -53,7 +53,8 @@ export class LinkAttachment {
|
||||
const foundLinkModel = await LinkModel().query(trx).findById(modelId);
|
||||
validateLinkModelEntryExists(foundLinkModel);
|
||||
|
||||
const foundLinks = await this.documentLinkModel().query(trx)
|
||||
const foundLinks = await this.documentLinkModel()
|
||||
.query(trx)
|
||||
.where('modelRef', modelRef)
|
||||
.where('modelId', modelId)
|
||||
.where('documentId', foundFile.id);
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface IContactAddress {
|
||||
billingAddressCity: string;
|
||||
billingAddressCountry: string;
|
||||
billingAddressEmail: string;
|
||||
billingAddressZipcode: string;
|
||||
billingAddressPostcode: string;
|
||||
billingAddressPhone: string;
|
||||
billingAddressState: string;
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface IContactAddress {
|
||||
shippingAddressCity: string;
|
||||
shippingAddressCountry: string;
|
||||
shippingAddressEmail: string;
|
||||
shippingAddressZipcode: string;
|
||||
shippingAddressPostcode: string;
|
||||
shippingAddressPhone: string;
|
||||
shippingAddressState: string;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export interface IContactAddressDTO {
|
||||
billingAddressCity?: string;
|
||||
billingAddressCountry?: string;
|
||||
billingAddressEmail?: string;
|
||||
billingAddressZipcode?: string;
|
||||
billingAddressPostcode?: string;
|
||||
billingAddressPhone?: string;
|
||||
billingAddressState?: string;
|
||||
|
||||
@@ -38,7 +38,7 @@ export interface IContactAddressDTO {
|
||||
shippingAddressCity?: string;
|
||||
shippingAddressCountry?: string;
|
||||
shippingAddressEmail?: string;
|
||||
shippingAddressZipcode?: string;
|
||||
shippingAddressPostcode?: string;
|
||||
shippingAddressPhone?: string;
|
||||
shippingAddressState?: string;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
@@ -14,6 +15,10 @@ import { PermissionGuard } from '@/modules/Roles/Permission.guard';
|
||||
import { AuthorizationGuard } from '@/modules/Roles/Authorization.guard';
|
||||
import { AbilitySubject } from '@/modules/Roles/Roles.types';
|
||||
import { CreditNoteAction } from '../CreditNotes/types/CreditNotes.types';
|
||||
import { GetCreditNoteAssociatedInvoicesToApply } from './queries/GetCreditNoteAssociatedInvoicesToApply.service';
|
||||
import { CreditNoteApplyToInvoices } from './commands/CreditNoteApplyToInvoices.service';
|
||||
import { DeleteCreditNoteApplyToInvoices } from './commands/DeleteCreditNoteApplyToInvoices.service';
|
||||
import { ApplyCreditNoteToInvoicesDto } from './dtos/ApplyCreditNoteToInvoices.dto';
|
||||
|
||||
@Controller('credit-notes')
|
||||
@ApiTags('Credit Notes Apply Invoice')
|
||||
@@ -22,6 +27,9 @@ import { CreditNoteAction } from '../CreditNotes/types/CreditNotes.types';
|
||||
export class CreditNotesApplyInvoiceController {
|
||||
constructor(
|
||||
private readonly getCreditNoteAssociatedAppliedInvoicesService: GetCreditNoteAssociatedAppliedInvoices,
|
||||
private readonly getCreditNoteAssociatedInvoicesToApplyService: GetCreditNoteAssociatedInvoicesToApply,
|
||||
private readonly creditNoteApplyToInvoicesService: CreditNoteApplyToInvoices,
|
||||
private readonly deleteCreditNoteApplyToInvoicesService: DeleteCreditNoteApplyToInvoices,
|
||||
) {}
|
||||
|
||||
@Get(':creditNoteId/applied-invoices')
|
||||
@@ -39,6 +47,23 @@ export class CreditNotesApplyInvoiceController {
|
||||
);
|
||||
}
|
||||
|
||||
@Get(':creditNoteId/apply-invoices')
|
||||
@RequirePermission(CreditNoteAction.View, AbilitySubject.CreditNote)
|
||||
@ApiOperation({ summary: 'Get credit note associated invoices to apply' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Credit note associated invoices to apply',
|
||||
})
|
||||
@ApiResponse({ status: 404, description: 'Credit note not found' })
|
||||
@ApiResponse({ status: 400, description: 'Invalid input data' })
|
||||
getCreditNoteAssociatedInvoicesToApply(
|
||||
@Param('creditNoteId') creditNoteId: number,
|
||||
) {
|
||||
return this.getCreditNoteAssociatedInvoicesToApplyService.getCreditAssociatedInvoicesToApply(
|
||||
creditNoteId,
|
||||
);
|
||||
}
|
||||
|
||||
@Post(':creditNoteId/apply-invoices')
|
||||
@RequirePermission(CreditNoteAction.Edit, AbilitySubject.CreditNote)
|
||||
@ApiOperation({ summary: 'Apply credit note to invoices' })
|
||||
@@ -48,9 +73,32 @@ export class CreditNotesApplyInvoiceController {
|
||||
})
|
||||
@ApiResponse({ status: 404, description: 'Credit note not found' })
|
||||
@ApiResponse({ status: 400, description: 'Invalid input data' })
|
||||
applyCreditNoteToInvoices(@Param('creditNoteId') creditNoteId: number) {
|
||||
return this.getCreditNoteAssociatedAppliedInvoicesService.getCreditAssociatedAppliedInvoices(
|
||||
applyCreditNoteToInvoices(
|
||||
@Param('creditNoteId') creditNoteId: number,
|
||||
@Body() applyDto: ApplyCreditNoteToInvoicesDto,
|
||||
) {
|
||||
return this.creditNoteApplyToInvoicesService.applyCreditNoteToInvoices(
|
||||
creditNoteId,
|
||||
applyDto,
|
||||
);
|
||||
}
|
||||
|
||||
@Delete('applied-invoices/:applyCreditToInvoicesId')
|
||||
@RequirePermission(CreditNoteAction.Edit, AbilitySubject.CreditNote)
|
||||
@ApiOperation({ summary: 'Delete applied credit note to invoice' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Credit note application successfully deleted',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 404,
|
||||
description: 'Credit note application not found',
|
||||
})
|
||||
deleteApplyCreditNoteToInvoices(
|
||||
@Param('applyCreditToInvoicesId') applyCreditToInvoicesId: number,
|
||||
) {
|
||||
return this.deleteCreditNoteApplyToInvoicesService.deleteApplyCreditNoteToInvoices(
|
||||
applyCreditToInvoicesId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import { CreditNotesModule } from '../CreditNotes/CreditNotes.module';
|
||||
import { GetCreditNoteAssociatedAppliedInvoices } from './queries/GetCreditNoteAssociatedAppliedInvoices.service';
|
||||
import { GetCreditNoteAssociatedInvoicesToApply } from './queries/GetCreditNoteAssociatedInvoicesToApply.service';
|
||||
import { CreditNotesApplyInvoiceController } from './CreditNotesApplyInvoice.controller';
|
||||
import { CreditNoteApplySyncCreditSubscriber } from './subscribers/CreditNoteApplySyncCreditSubscriber';
|
||||
import { CreditNoteApplySyncInvoicesCreditedAmountSubscriber } from './subscribers/CreditNoteApplySyncInvoicesSubscriber';
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
@@ -19,6 +21,8 @@ import { CreditNotesApplyInvoiceController } from './CreditNotesApplyInvoice.con
|
||||
CreditNoteApplySyncCredit,
|
||||
GetCreditNoteAssociatedAppliedInvoices,
|
||||
GetCreditNoteAssociatedInvoicesToApply,
|
||||
CreditNoteApplySyncCreditSubscriber,
|
||||
CreditNoteApplySyncInvoicesCreditedAmountSubscriber,
|
||||
],
|
||||
exports: [DeleteCustomerLinkedCreditNoteService],
|
||||
imports: [PaymentsReceivedModule, forwardRef(() => CreditNotesModule)],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import Bluebird from 'bluebird';
|
||||
import * as Bluebird from 'bluebird';
|
||||
import { ICreditNoteAppliedToInvoice } from '../types/CreditNoteApplyInvoice.types';
|
||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||
import { CreditNoteAppliedInvoice } from '../models/CreditNoteAppliedInvoice';
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { sumBy } from 'lodash';
|
||||
import {
|
||||
ICreditNoteAppliedToInvoice,
|
||||
ICreditNoteAppliedToInvoiceModel,
|
||||
IApplyCreditToInvoicesDTO,
|
||||
IApplyCreditToInvoicesCreatedPayload,
|
||||
@@ -17,6 +18,7 @@ import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||
import { CreditNoteAppliedInvoice } from '../models/CreditNoteAppliedInvoice';
|
||||
import { CommandCreditNoteDTOTransform } from '@/modules/CreditNotes/commands/CommandCreditNoteDTOTransform.service';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ApplyCreditNoteToInvoicesDto } from '../dtos/ApplyCreditNoteToInvoices.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNoteApplyToInvoices {
|
||||
@@ -48,7 +50,7 @@ export class CreditNoteApplyToInvoices {
|
||||
*/
|
||||
public async applyCreditNoteToInvoices(
|
||||
creditNoteId: number,
|
||||
applyCreditToInvoicesDTO: IApplyCreditToInvoicesDTO,
|
||||
applyCreditToInvoicesDTO: ApplyCreditNoteToInvoicesDto,
|
||||
): Promise<CreditNoteAppliedInvoice[]> {
|
||||
// Saves the credit note or throw not found service error.
|
||||
const creditNote = await this.creditNoteModel()
|
||||
@@ -71,7 +73,7 @@ export class CreditNoteApplyToInvoices {
|
||||
// Validate invoices has remaining amount to apply.
|
||||
this.validateInvoicesRemainingAmount(
|
||||
appliedInvoicesEntries,
|
||||
creditNoteAppliedModel.amount,
|
||||
creditNoteAppliedModel.entries,
|
||||
);
|
||||
// Validate the credit note remaining amount.
|
||||
this.creditNoteDTOTransform.validateCreditRemainingAmount(
|
||||
@@ -122,18 +124,20 @@ export class CreditNoteApplyToInvoices {
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate the invoice remaining amount.
|
||||
* Validate each invoice has sufficient remaining amount for the applied credit.
|
||||
* @param {ISaleInvoice[]} invoices
|
||||
* @param {number} amount
|
||||
* @param {ICreditNoteAppliedToInvoice[]} entries
|
||||
*/
|
||||
private validateInvoicesRemainingAmount = (
|
||||
invoices: SaleInvoice[],
|
||||
amount: number,
|
||||
entries: ICreditNoteAppliedToInvoice[],
|
||||
) => {
|
||||
const invalidInvoices = invoices.filter(
|
||||
(invoice) => invoice.dueAmount < amount,
|
||||
);
|
||||
if (invalidInvoices.length > 0) {
|
||||
const invoiceMap = new Map(invoices.map((inv) => [inv.id, inv]));
|
||||
const invalidEntries = entries.filter((entry) => {
|
||||
const invoice = invoiceMap.get(entry.invoiceId);
|
||||
return invoice != null && invoice.dueAmount < entry.amount;
|
||||
});
|
||||
if (invalidEntries.length > 0) {
|
||||
throw new ServiceError(ERRORS.INVOICES_HAS_NO_REMAINING_AMOUNT);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
ArrayMinSize,
|
||||
IsArray,
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
|
||||
export class ApplyCreditNoteInvoiceEntryDto {
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@ApiProperty({ description: 'Invoice ID to apply credit to', example: 1 })
|
||||
invoiceId: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
@ApiProperty({ description: 'Amount to apply', example: 100.5 })
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export class ApplyCreditNoteToInvoicesDto {
|
||||
@IsArray()
|
||||
@ArrayMinSize(1)
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => ApplyCreditNoteInvoiceEntryDto)
|
||||
@ApiProperty({
|
||||
description: 'Entries of invoice ID and amount to apply',
|
||||
type: [ApplyCreditNoteInvoiceEntryDto],
|
||||
example: [
|
||||
{ invoice_id: 1, amount: 100.5 },
|
||||
{ invoice_id: 2, amount: 50 },
|
||||
],
|
||||
})
|
||||
entries: ApplyCreditNoteInvoiceEntryDto[];
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import { CreditNoteApplySyncInvoicesCreditedAmount } from '../commands/CreditNot
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export default class CreditNoteApplySyncInvoicesCreditedAmountSubscriber {
|
||||
export class CreditNoteApplySyncInvoicesCreditedAmountSubscriber {
|
||||
constructor(
|
||||
private readonly syncInvoicesWithCreditNote: CreditNoteApplySyncInvoicesCreditedAmount,
|
||||
) {}
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface IApplyCreditToInvoicesDeletedPayload {
|
||||
export interface ICreditNoteAppliedToInvoice {
|
||||
amount: number;
|
||||
creditNoteId: number;
|
||||
invoiceId: number;
|
||||
}
|
||||
export interface ICreditNoteAppliedToInvoiceModel {
|
||||
amount: number;
|
||||
|
||||
@@ -27,10 +27,10 @@ export class ContactAddressDto {
|
||||
@IsEmail()
|
||||
billingAddressEmail?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address zipcode' })
|
||||
@ApiProperty({ required: false, description: 'Billing address postcode' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddressZipcode?: string;
|
||||
billingAddressPostcode?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address phone' })
|
||||
@IsOptional()
|
||||
@@ -67,10 +67,10 @@ export class ContactAddressDto {
|
||||
@IsEmail()
|
||||
shippingAddressEmail?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address zipcode' })
|
||||
@ApiProperty({ required: false, description: 'Shipping address postcode' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddressZipcode?: string;
|
||||
shippingAddressPostcode?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address phone' })
|
||||
@IsOptional()
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import currencies from 'js-money/lib/currency';
|
||||
|
||||
export const DATE_FORMATS = [
|
||||
'MM.dd.yy',
|
||||
'dd.MM.yy',
|
||||
'yy.MM.dd',
|
||||
'MM.dd.yyyy',
|
||||
'dd.MM.yyyy',
|
||||
'yyyy.MM.dd',
|
||||
'MM/DD/YYYY',
|
||||
'M/D/YYYY',
|
||||
'dd MMM YYYY',
|
||||
'dd MMMM YYYY',
|
||||
'MMMM dd, YYYY',
|
||||
'EEE, MMMM dd, YYYY',
|
||||
'MM/DD/YY',
|
||||
'DD/MM/YY',
|
||||
'YY/MM/DD',
|
||||
'MM/DD/yyyy',
|
||||
'DD/MM/yyyy',
|
||||
'yyyy/MM/DD',
|
||||
'DD MMM YYYY',
|
||||
'DD MMMM YYYY',
|
||||
'MMMM DD, YYYY',
|
||||
];
|
||||
export const MONTHS = [
|
||||
'january',
|
||||
|
||||
@@ -12,6 +12,6 @@ export const transformBuildDto = (
|
||||
): BuildOrganizationDto => {
|
||||
return {
|
||||
...buildDTO,
|
||||
dateFormat: defaultTo(buildDTO.dateFormat, 'DD MMM yyyy'),
|
||||
dateFormat: defaultTo(buildDTO.dateFormat, 'DD MMM YYYY'),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Bluebird from 'bluebird';
|
||||
import * as Bluebird from 'bluebird';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { IVendorCreditAppliedBill } from '../types/VendorCreditApplyBills.types';
|
||||
|
||||
@@ -48,7 +48,10 @@ export class EditVendorDto extends ContactAddressDto {
|
||||
@IsString()
|
||||
personalPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Additional notes about the vendor' })
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Additional notes about the vendor',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
note?: string;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
.root {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title{
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
color: #252A31;
|
||||
}
|
||||
|
||||
.description{
|
||||
margin-bottom: 1rem;
|
||||
font-size: 15px;
|
||||
line-height: 1.45;
|
||||
color: #404854;
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
// @ts-nocheck
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import AuthInsider from './AuthInsider';
|
||||
import { AuthInsiderCard } from './_components';
|
||||
import styles from './RegisterVerify.module.scss';
|
||||
import { AppToaster, Stack } from '@/components';
|
||||
import { useAuthActions, useAuthUserVerifyEmail } from '@/hooks/state';
|
||||
import { useAuthSignUpVerifyResendMail } from '@/hooks/query';
|
||||
import { AuthContainer } from './AuthContainer';
|
||||
import { useIsDarkMode } from '@/hooks/useDarkMode';
|
||||
|
||||
export default function RegisterVerify() {
|
||||
const { setLogout } = useAuthActions();
|
||||
@@ -14,6 +15,7 @@ export default function RegisterVerify() {
|
||||
useAuthSignUpVerifyResendMail();
|
||||
|
||||
const emailAddress = useAuthUserVerifyEmail();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const handleResendMailBtnClick = () => {
|
||||
resendSignUpVerifyMail()
|
||||
@@ -37,12 +39,24 @@ export default function RegisterVerify() {
|
||||
return (
|
||||
<AuthContainer>
|
||||
<AuthInsider>
|
||||
<AuthInsiderCard className={styles.root}>
|
||||
<h2 className={styles.title}>Please verify your email</h2>
|
||||
<p className={styles.description}>
|
||||
<AuthInsiderCard textAlign="center">
|
||||
<x.h2
|
||||
fontSize="18px"
|
||||
fontWeight={600}
|
||||
mb="0.5rem"
|
||||
color={isDarkMode ? 'rgba(255, 255, 255, 0.85)' : '#252A31'}
|
||||
>
|
||||
Please verify your email
|
||||
</x.h2>
|
||||
<x.p
|
||||
mb="1rem"
|
||||
fontSize="15px"
|
||||
lineHeight="1.45"
|
||||
color={isDarkMode ? 'rgba(255, 255, 255, 0.7)' : '#404854'}
|
||||
>
|
||||
We sent an email to <strong>{emailAddress}</strong> Click the link
|
||||
inside to get started.
|
||||
</p>
|
||||
</x.p>
|
||||
|
||||
<Stack spacing={4}>
|
||||
<Button
|
||||
|
||||
@@ -27,20 +27,20 @@ const CustomerBillingAddress = ({}) => {
|
||||
|
||||
{/*------------ Billing Address 1 -----------*/}
|
||||
<FFormGroup
|
||||
name={'billing_address_1'}
|
||||
name={'billing_address1'}
|
||||
label={<T id={'address_line_1'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'billing_address_1'} />
|
||||
<FTextArea name={'billing_address1'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Billing Address 2 -----------*/}
|
||||
<FFormGroup
|
||||
name={'billing_address_2'}
|
||||
name={'billing_address2'}
|
||||
label={<T id={'address_line_2'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'billing_address_2'} />
|
||||
<FTextArea name={'billing_address2'} />
|
||||
</FFormGroup>
|
||||
{/*------------ Billing Address city -----------*/}
|
||||
<FFormGroup
|
||||
@@ -93,20 +93,20 @@ const CustomerBillingAddress = ({}) => {
|
||||
|
||||
{/*------------ Shipping Address 1 -----------*/}
|
||||
<FFormGroup
|
||||
name={'shipping_address_1'}
|
||||
name={'shipping_address1'}
|
||||
label={<T id={'address_line_1'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'shipping_address_1'} />
|
||||
<FTextArea name={'shipping_address1'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Shipping Address 2 -----------*/}
|
||||
<FFormGroup
|
||||
name={'shipping_address_2'}
|
||||
name={'shipping_address2'}
|
||||
label={<T id={'address_line_2'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'shipping_address_2'} />
|
||||
<FTextArea name={'shipping_address2'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Shipping Address city -----------*/}
|
||||
|
||||
@@ -25,16 +25,16 @@ const Schema = Yup.object().shape({
|
||||
note: Yup.string().trim(),
|
||||
|
||||
billing_address_country: Yup.string().trim(),
|
||||
billing_address_1: Yup.string().trim(),
|
||||
billing_address_2: Yup.string().trim(),
|
||||
billing_address1: Yup.string().trim(),
|
||||
billing_address2: Yup.string().trim(),
|
||||
billing_address_city: Yup.string().trim(),
|
||||
billing_address_state: Yup.string().trim(),
|
||||
billing_address_postcode: Yup.string().nullable(),
|
||||
billing_address_phone: Yup.string().nullable(),
|
||||
|
||||
shipping_address_country: Yup.string().trim(),
|
||||
shipping_address_1: Yup.string().trim(),
|
||||
shipping_address_2: Yup.string().trim(),
|
||||
shipping_address1: Yup.string().trim(),
|
||||
shipping_address2: Yup.string().trim(),
|
||||
shipping_address_city: Yup.string().trim(),
|
||||
shipping_address_state: Yup.string().trim(),
|
||||
shipping_address_postcode: Yup.string().nullable(),
|
||||
|
||||
@@ -8,7 +8,7 @@ import styled from 'styled-components';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { CreateCustomerForm, EditCustomerForm } from './CustomerForm.schema';
|
||||
import { compose, transformToForm, saveInvoke } from '@/utils';
|
||||
import { compose, transformToForm, saveInvoke, parseBoolean } from '@/utils';
|
||||
import { useCustomerFormContext } from './CustomerFormProvider';
|
||||
import { defaultInitialValues } from './utils';
|
||||
|
||||
@@ -60,7 +60,10 @@ function CustomerFormFormik({
|
||||
// Handles the form submit.
|
||||
const handleFormSubmit = (values, formArgs) => {
|
||||
const { setSubmitting, resetForm } = formArgs;
|
||||
const formValues = { ...values };
|
||||
const formValues = {
|
||||
...values,
|
||||
active: parseBoolean(values.active, true),
|
||||
};
|
||||
|
||||
const onSuccess = (res) => {
|
||||
AppToaster.show({
|
||||
|
||||
@@ -55,7 +55,7 @@ export default function CustomerFormPrimarySection({}) {
|
||||
label={<T id={'company_name'} />}
|
||||
inline={true}
|
||||
>
|
||||
<InputGroup name={'company_name'} />
|
||||
<FInputGroup name={'company_name'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*----------- Display Name -----------*/}
|
||||
|
||||
@@ -23,16 +23,16 @@ export const defaultInitialValues = {
|
||||
active: true,
|
||||
|
||||
billing_address_country: '',
|
||||
billing_address_1: '',
|
||||
billing_address_2: '',
|
||||
billing_address1: '',
|
||||
billing_address2: '',
|
||||
billing_address_city: '',
|
||||
billing_address_state: '',
|
||||
billing_address_postcode: '',
|
||||
billing_address_phone: '',
|
||||
|
||||
shipping_address_country: '',
|
||||
shipping_address_1: '',
|
||||
shipping_address_2: '',
|
||||
shipping_address1: '',
|
||||
shipping_address2: '',
|
||||
shipping_address_city: '',
|
||||
shipping_address_state: '',
|
||||
shipping_address_postcode: '',
|
||||
|
||||
@@ -111,12 +111,12 @@ export default function PreferencesGeneralForm({ isSubmitting }) {
|
||||
>
|
||||
<Stack>
|
||||
<FInputGroup
|
||||
name={'address.address_1'}
|
||||
name={'address.address1'}
|
||||
placeholder={'Address 1'}
|
||||
fastField
|
||||
/>
|
||||
<FInputGroup
|
||||
name={'address.address_2'}
|
||||
name={'address.address2'}
|
||||
placeholder={'Address 2'}
|
||||
fastField
|
||||
/>
|
||||
|
||||
@@ -18,16 +18,16 @@ const Schema = Yup.object().shape({
|
||||
note: Yup.string().trim(),
|
||||
|
||||
billing_address_country: Yup.string().trim(),
|
||||
billing_address_1: Yup.string().trim(),
|
||||
billing_address_2: Yup.string().trim(),
|
||||
billing_address1: Yup.string().trim(),
|
||||
billing_address2: Yup.string().trim(),
|
||||
billing_address_city: Yup.string().trim(),
|
||||
billing_address_state: Yup.string().trim(),
|
||||
billing_address_postcode: Yup.string().nullable(),
|
||||
billing_address_phone: Yup.string().nullable(),
|
||||
|
||||
shipping_address_country: Yup.string().trim(),
|
||||
shipping_address_1: Yup.string().trim(),
|
||||
shipping_address_2: Yup.string().trim(),
|
||||
shipping_address1: Yup.string().trim(),
|
||||
shipping_address2: Yup.string().trim(),
|
||||
shipping_address_city: Yup.string().trim(),
|
||||
shipping_address_state: Yup.string().trim(),
|
||||
shipping_address_postcode: Yup.string().nullable(),
|
||||
|
||||
@@ -21,7 +21,7 @@ import VendorFloatingActions from './VendorFloatingActions';
|
||||
import { withCurrentOrganization } from '@/containers/Organization/withCurrentOrganization';
|
||||
|
||||
import { useVendorFormContext } from './VendorFormProvider';
|
||||
import { compose, transformToForm, safeInvoke } from '@/utils';
|
||||
import { compose, transformToForm, safeInvoke, parseBoolean } from '@/utils';
|
||||
import { defaultInitialValues } from './utils';
|
||||
|
||||
import '@/style/pages/Vendors/Form.scss';
|
||||
@@ -69,7 +69,10 @@ function VendorFormFormik({
|
||||
// Handles the form submit.
|
||||
const handleFormSubmit = (values, form) => {
|
||||
const { setSubmitting, resetForm } = form;
|
||||
const requestForm = { ...values };
|
||||
const requestForm = {
|
||||
...values,
|
||||
active: parseBoolean(values.active, true),
|
||||
};
|
||||
|
||||
setSubmitting(true);
|
||||
|
||||
|
||||
@@ -22,16 +22,16 @@ export const defaultInitialValues = {
|
||||
active: true,
|
||||
|
||||
billing_address_country: '',
|
||||
billing_address_1: '',
|
||||
billing_address_2: '',
|
||||
billing_address1: '',
|
||||
billing_address2: '',
|
||||
billing_address_city: '',
|
||||
billing_address_state: '',
|
||||
billing_address_postcode: '',
|
||||
billing_address_phone: '',
|
||||
|
||||
shipping_address_country: '',
|
||||
shipping_address_1: '',
|
||||
shipping_address_2: '',
|
||||
shipping_address1: '',
|
||||
shipping_address2: '',
|
||||
shipping_address_city: '',
|
||||
shipping_address_state: '',
|
||||
shipping_address_postcode: '',
|
||||
|
||||
@@ -58,16 +58,13 @@ export function useCreateCreditNote(props) {
|
||||
const queryClient = useQueryClient();
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useMutation(
|
||||
(values) => apiRequest.post('credit-notes', values),
|
||||
{
|
||||
return useMutation((values) => apiRequest.post('credit-notes', values), {
|
||||
onSuccess: (res, values) => {
|
||||
// Common invalidate queries.
|
||||
commonInvalidateQueries(queryClient);
|
||||
},
|
||||
...props,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,8 +215,7 @@ export function useCreateRefundCreditNote(props) {
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useMutation(
|
||||
([id, values]) =>
|
||||
apiRequest.post(`credit-notes/${id}/refunds`, values),
|
||||
([id, values]) => apiRequest.post(`credit-notes/${id}/refunds`, values),
|
||||
{
|
||||
onSuccess: (res, [id, values]) => {
|
||||
// Common invalidate queries.
|
||||
@@ -240,9 +236,7 @@ export function useDeleteRefundCreditNote(props) {
|
||||
const queryClient = useQueryClient();
|
||||
const apiRequest = useApiRequest();
|
||||
|
||||
return useMutation(
|
||||
(id) => apiRequest.delete(`credit-notes/refunds/${id}`),
|
||||
{
|
||||
return useMutation((id) => apiRequest.delete(`credit-notes/refunds/${id}`), {
|
||||
onSuccess: (res, id) => {
|
||||
// Common invalidate queries.
|
||||
commonInvalidateQueries(queryClient);
|
||||
@@ -251,8 +245,7 @@ export function useDeleteRefundCreditNote(props) {
|
||||
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
|
||||
},
|
||||
...props,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,7 +294,7 @@ export function useReconcileCreditNote(id, props, requestProps) {
|
||||
[t.RECONCILE_CREDIT_NOTE, id],
|
||||
{
|
||||
method: 'get',
|
||||
url: `credit-notes/${id}/applied-invoices`,
|
||||
url: `credit-notes/${id}/apply-invoices`,
|
||||
...requestProps,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -84,6 +84,20 @@ export const handleBooleanChange = (handler) => {
|
||||
return (event) => handler(event.target.checked);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a value to boolean (handles 1, 0, '1', '0', true, false).
|
||||
* @param {*} value
|
||||
* @param {boolean} defaultValue - value when empty/unknown
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const parseBoolean = (value, defaultValue = false) => {
|
||||
if (typeof value === 'boolean') return value;
|
||||
if (value === 1 || value === '1') return true;
|
||||
if (value === 0 || value === '0') return false;
|
||||
if (value == null || value === '') return defaultValue;
|
||||
return Boolean(value);
|
||||
};
|
||||
|
||||
/** Event handler that exposes the target element's value as a string. */
|
||||
export const handleStringChange = (handler) => {
|
||||
return (event) => handler(event.target.value);
|
||||
|
||||
Reference in New Issue
Block a user