From 09b7e74d654bc7acc2c59660ed650abcd6b02ba9 Mon Sep 17 00:00:00 2001 From: Camilo Oviedo Date: Wed, 14 Aug 2024 16:21:48 +1000 Subject: [PATCH 1/6] fix: Enhance visual feedback on file drag-and-drop --- .../components/Dropzone/Dropzone.module.css | 34 ++++++++++++++++--- .../src/components/Dropzone/Dropzone.tsx | 14 +++++--- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/packages/webapp/src/components/Dropzone/Dropzone.module.css b/packages/webapp/src/components/Dropzone/Dropzone.module.css index 63a207805..4681110b5 100644 --- a/packages/webapp/src/components/Dropzone/Dropzone.module.css +++ b/packages/webapp/src/components/Dropzone/Dropzone.module.css @@ -1,12 +1,38 @@ - - .root { padding: 20px; - border: 2px dotted #c5cbd3; + border: 2px dashed #c5cbd3; /* Changed from dotted to dashed for better visibility */ border-radius: 6px; min-height: 200px; display: flex; flex-direction: column; background: #fff; position: relative; -} \ No newline at end of file + transition: background-color 0.3s ease, border-color 0.3s ease; +} + +.dropzoneActive { + background-color: rgba(0, 123, 255, 0.15); + border-color: #007bff; +} + +.dropzoneActive .content { + color: #007bff; /* Change text color to match the border when active */ +} + +.content { + position: relative; + z-index: 20; + transition: color 0.3s ease; +} + +.dropzoneActive:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 123, 255, 0.3); /* This creates a full overlay effect */ + z-index: 10; + border-radius: 6px; /* Ensures the overlay matches the container's rounded corners */ +} diff --git a/packages/webapp/src/components/Dropzone/Dropzone.tsx b/packages/webapp/src/components/Dropzone/Dropzone.tsx index 8682a499b..e885407b5 100644 --- a/packages/webapp/src/components/Dropzone/Dropzone.tsx +++ b/packages/webapp/src/components/Dropzone/Dropzone.tsx @@ -28,9 +28,9 @@ export type DropzoneCssVariables = { }; export interface DropzoneProps { - /** Key of `theme.colors` or any valid CSS color to set colors of `Dropzone.Accept`, `theme.primaryColor` by default */ + /** Key of `theme.colors` or any valid CSS color to set colors of `Dropzone.Accept`, `theme.primaryColor` by default */ acceptColor?: MantineColor; - + /** Key of `theme.colors` or any valid CSS color to set colors of `Dropzone.Reject`, `'red'` by default */ rejectColor?: MantineColor; @@ -235,7 +235,13 @@ export const Dropzone = (_props: DropzoneProps) => { > {
{children}
From 9b8b51cb9129d5e701181f51417e3ae9fcd408a3 Mon Sep 17 00:00:00 2001 From: Camilo Oviedo Date: Wed, 14 Aug 2024 16:29:38 +1000 Subject: [PATCH 2/6] fix: Enhance visual feedback on file drag-and-drop --- packages/webapp/src/components/Dropzone/Dropzone.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/components/Dropzone/Dropzone.tsx b/packages/webapp/src/components/Dropzone/Dropzone.tsx index e885407b5..1c0914385 100644 --- a/packages/webapp/src/components/Dropzone/Dropzone.tsx +++ b/packages/webapp/src/components/Dropzone/Dropzone.tsx @@ -28,9 +28,9 @@ export type DropzoneCssVariables = { }; export interface DropzoneProps { - /** Key of `theme.colors` or any valid CSS color to set colors of `Dropzone.Accept`, `theme.primaryColor` by default */ + /** Key of `theme.colors` or any valid CSS color to set colors of `Dropzone.Accept`, `theme.primaryColor` by default */ acceptColor?: MantineColor; - + /** Key of `theme.colors` or any valid CSS color to set colors of `Dropzone.Reject`, `'red'` by default */ rejectColor?: MantineColor; From f97b127a69bcd716b426a43e5f94a9aa53c572c0 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 14 Aug 2024 16:12:13 +0200 Subject: [PATCH 3/6] fix: style tweaks in dropzoen accept/reject modes --- .../components/Dropzone/Dropzone.module.css | 38 +++++-------------- .../src/components/Dropzone/Dropzone.tsx | 5 +-- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/packages/webapp/src/components/Dropzone/Dropzone.module.css b/packages/webapp/src/components/Dropzone/Dropzone.module.css index 4681110b5..907edbf30 100644 --- a/packages/webapp/src/components/Dropzone/Dropzone.module.css +++ b/packages/webapp/src/components/Dropzone/Dropzone.module.css @@ -1,6 +1,6 @@ .root { padding: 20px; - border: 2px dashed #c5cbd3; /* Changed from dotted to dashed for better visibility */ + border: 2px dotted #c5cbd3; border-radius: 6px; min-height: 200px; display: flex; @@ -8,31 +8,13 @@ background: #fff; position: relative; transition: background-color 0.3s ease, border-color 0.3s ease; -} -.dropzoneActive { - background-color: rgba(0, 123, 255, 0.15); - border-color: #007bff; -} - -.dropzoneActive .content { - color: #007bff; /* Change text color to match the border when active */ -} - -.content { - position: relative; - z-index: 20; - transition: color 0.3s ease; -} - -.dropzoneActive:before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 123, 255, 0.3); /* This creates a full overlay effect */ - z-index: 10; - border-radius: 6px; /* Ensures the overlay matches the container's rounded corners */ -} + &.dropzoneAccept { + border-color: rgb(0, 82, 204); + background: rgba(0, 82, 204, 0.05); + } + &.dropzoneReject { + border-color: #AC2F33; + background: rgba(172, 47, 51, 0.05) + } +} \ No newline at end of file diff --git a/packages/webapp/src/components/Dropzone/Dropzone.tsx b/packages/webapp/src/components/Dropzone/Dropzone.tsx index 1c0914385..bc0d45b46 100644 --- a/packages/webapp/src/components/Dropzone/Dropzone.tsx +++ b/packages/webapp/src/components/Dropzone/Dropzone.tsx @@ -238,7 +238,8 @@ export const Dropzone = (_props: DropzoneProps) => { className: clsx( styles.root, { - [styles.dropzoneActive]: isDragAccept || isDragReject, + [styles.dropzoneAccept]: isDragAccept, + [styles.dropzoneReject]: isDragReject }, classNames?.root ), @@ -274,8 +275,6 @@ Dropzone.Idle = DropzoneIdle; Dropzone.Reject = DropzoneReject; - - type PossibleRef = Ref | undefined; export function assignRef(ref: PossibleRef, value: T) { From f6ce761a271e072ff390a67eb5a91eb2e15cd0d2 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:20:50 +0200 Subject: [PATCH 4/6] docs: add Champetaman as a contributor for code (#605) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index a2e0d8553..fa713e515 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -150,6 +150,15 @@ "contributions": [ "bug" ] + }, + { + "login": "Champetaman", + "name": "Camilo Oviedo", + "avatar_url": "https://avatars.githubusercontent.com/u/64604272?v=4", + "profile": "https://www.camilooviedo.com/", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 463957cf3..061f908b5 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Denis
Denis

🐛 Sachin Mittal
Sachin Mittal

🐛 + Camilo Oviedo
Camilo Oviedo

💻 From b12f090d130859ddb4fac6c58500ff1e670aa8a6 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 14 Aug 2024 19:23:15 +0200 Subject: [PATCH 5/6] fix: matching bank transactions should create associate payment transactions for bills and invoicese. (#606) --- .../server/src/interfaces/PaymentReceive.ts | 2 +- .../Matching/GetMatchedTransactionsByBills.ts | 73 ++++++++++++++++++- .../GetMatchedTransactionsByInvoices.ts | 70 +++++++++++++++++- 3 files changed, 137 insertions(+), 8 deletions(-) diff --git a/packages/server/src/interfaces/PaymentReceive.ts b/packages/server/src/interfaces/PaymentReceive.ts index e9910b709..b7c216abd 100644 --- a/packages/server/src/interfaces/PaymentReceive.ts +++ b/packages/server/src/interfaces/PaymentReceive.ts @@ -67,7 +67,7 @@ export interface IPaymentReceivedEntry { export interface IPaymentReceivedEntryDTO { id?: number; index: number; - paymentReceiveId: number; + paymentReceiveId?: number; invoiceId: number; paymentAmount: number; } diff --git a/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByBills.ts b/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByBills.ts index 394fecba5..b9b85cb8c 100644 --- a/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByBills.ts +++ b/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByBills.ts @@ -1,18 +1,25 @@ import { Inject, Service } from 'typedi'; import { initialize } from 'objection'; +import { Knex } from 'knex'; +import { first } from 'lodash'; import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable'; import { GetMatchedTransactionBillsTransformer } from './GetMatchedTransactionBillsTransformer'; -import { GetMatchedTransactionsFilter, MatchedTransactionPOJO } from './types'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; +import { + GetMatchedTransactionsFilter, + IMatchTransactionDTO, + MatchedTransactionPOJO, +} from './types'; import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType'; +import { CreateBillPayment } from '@/services/Purchases/BillPayments/CreateBillPayment'; +import { IBillPaymentDTO } from '@/interfaces'; @Service() export class GetMatchedTransactionsByBills extends GetMatchedTransactionsByType { @Inject() - private tenancy: HasTenancyService; + private transformer: TransformerInjectable; @Inject() - private transformer: TransformerInjectable; + private createPaymentMadeService: CreateBillPayment; /** * Retrieves the matched transactions. @@ -71,4 +78,62 @@ export class GetMatchedTransactionsByBills extends GetMatchedTransactionsByType new GetMatchedTransactionBillsTransformer() ); } + + /** + * Creates the common matched transaction. + * @param {number} tenantId + * @param {Array} uncategorizedTransactionIds + * @param {IMatchTransactionDTO} matchTransactionDTO + * @param {Knex.Transaction} trx + */ + public async createMatchedTransaction( + tenantId: number, + uncategorizedTransactionIds: Array, + matchTransactionDTO: IMatchTransactionDTO, + trx?: Knex.Transaction + ): Promise { + await super.createMatchedTransaction( + tenantId, + uncategorizedTransactionIds, + matchTransactionDTO, + trx + ); + const { Bill, UncategorizedCashflowTransaction, MatchedBankTransaction } = + this.tenancy.models(tenantId); + + const uncategorizedTransactionId = first(uncategorizedTransactionIds); + const uncategorizedTransaction = + await UncategorizedCashflowTransaction.query(trx) + .findById(uncategorizedTransactionId) + .throwIfNotFound(); + + const bill = await Bill.query(trx) + .findById(matchTransactionDTO.referenceId) + .throwIfNotFound(); + + const createPaymentMadeDTO: IBillPaymentDTO = { + vendorId: bill.vendorId, + paymentAccountId: uncategorizedTransaction.accountId, + paymentDate: uncategorizedTransaction.date, + exchangeRate: 1, + entries: [ + { + paymentAmount: bill.dueAmount, + billId: bill.id, + }, + ], + branchId: bill.branchId, + }; + // Create a new bill payment associated to the matched bill. + const billPayment = await this.createPaymentMadeService.createBillPayment( + tenantId, + createPaymentMadeDTO, + trx + ); + // Link the create bill payment with matched transaction. + await super.createMatchedTransaction(tenantId, uncategorizedTransactionIds, { + referenceType: 'BillPayment', + referenceId: billPayment.id, + }, trx); + } } diff --git a/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByInvoices.ts b/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByInvoices.ts index 88cc72c1e..1d7baee7a 100644 --- a/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByInvoices.ts +++ b/packages/server/src/services/Banking/Matching/GetMatchedTransactionsByInvoices.ts @@ -1,22 +1,26 @@ import { Inject, Service } from 'typedi'; import { initialize } from 'objection'; +import { Knex } from 'knex'; +import { first } from 'lodash'; import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable'; import { GetMatchedTransactionInvoicesTransformer } from './GetMatchedTransactionInvoicesTransformer'; import { GetMatchedTransactionsFilter, + IMatchTransactionDTO, MatchedTransactionPOJO, MatchedTransactionsPOJO, } from './types'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType'; +import { CreatePaymentReceived } from '@/services/Sales/PaymentReceived/CreatePaymentReceived'; +import { IPaymentReceivedCreateDTO } from '@/interfaces'; @Service() export class GetMatchedTransactionsByInvoices extends GetMatchedTransactionsByType { @Inject() - protected tenancy: HasTenancyService; + protected transformer: TransformerInjectable; @Inject() - protected transformer: TransformerInjectable; + protected createPaymentReceivedService: CreatePaymentReceived; /** * Retrieves the matched transactions. @@ -78,4 +82,64 @@ export class GetMatchedTransactionsByInvoices extends GetMatchedTransactionsByTy new GetMatchedTransactionInvoicesTransformer() ); } + + /** + * Creates the common matched transaction. + * @param {number} tenantId + * @param {Array} uncategorizedTransactionIds + * @param {IMatchTransactionDTO} matchTransactionDTO + * @param {Knex.Transaction} trx + */ + public async createMatchedTransaction( + tenantId: number, + uncategorizedTransactionIds: Array, + matchTransactionDTO: IMatchTransactionDTO, + trx?: Knex.Transaction + ) { + await super.createMatchedTransaction( + tenantId, + uncategorizedTransactionIds, + matchTransactionDTO, + trx + ); + const { SaleInvoice, UncategorizedCashflowTransaction, MatchedBankTransaction } = + this.tenancy.models(tenantId); + + const uncategorizedTransactionId = first(uncategorizedTransactionIds); + const uncategorizedTransaction = + await UncategorizedCashflowTransaction.query(trx) + .findById(uncategorizedTransactionId) + .throwIfNotFound(); + + const invoice = await SaleInvoice.query(trx) + .findById(matchTransactionDTO.referenceId) + .throwIfNotFound(); + + const createPaymentReceivedDTO: IPaymentReceivedCreateDTO = { + customerId: invoice.customerId, + paymentDate: uncategorizedTransaction.date, + amount: invoice.dueAmount, + depositAccountId: uncategorizedTransaction.accountId, + entries: [ + { + index: 1, + invoiceId: invoice.id, + paymentAmount: invoice.dueAmount, + }, + ], + branchId: invoice.branchId, + }; + // Create a payment received associated to the matched invoice. + const paymentReceived = await this.createPaymentReceivedService.createPaymentReceived( + tenantId, + createPaymentReceivedDTO, + {}, + trx + ); + // Link the create payment received with matched invoice transaction. + await super.createMatchedTransaction(tenantId, uncategorizedTransactionIds, { + referenceType: 'PaymentReceive', + referenceId: paymentReceived.id, + }, trx) + } } From ee96dc68cc789d9412d66f8c21aaaa78ed3d3132 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 14 Aug 2024 20:13:45 +0200 Subject: [PATCH 6/6] fix: Change Dropzone title and subtitle (#607) --- .../containers/Attachments/UploadAttachmentsPopoverContent.tsx | 1 + packages/webapp/src/containers/Import/ImportDropzone.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/webapp/src/containers/Attachments/UploadAttachmentsPopoverContent.tsx b/packages/webapp/src/containers/Attachments/UploadAttachmentsPopoverContent.tsx index d7a5b8c1e..f755b42b4 100644 --- a/packages/webapp/src/containers/Attachments/UploadAttachmentsPopoverContent.tsx +++ b/packages/webapp/src/containers/Attachments/UploadAttachmentsPopoverContent.tsx @@ -120,6 +120,7 @@ export function UploadAttachmentsPopoverContent({ uploadIcon={null} value={null} title={''} + subtitle={'Drag and drop file here or choose file'} classNames={{ root: styles.dropzoneRoot }} onChange={handleChangeDropzone} dropzoneProps={{ diff --git a/packages/webapp/src/containers/Import/ImportDropzone.tsx b/packages/webapp/src/containers/Import/ImportDropzone.tsx index 5dae46d06..43ff50b8c 100644 --- a/packages/webapp/src/containers/Import/ImportDropzone.tsx +++ b/packages/webapp/src/containers/Import/ImportDropzone.tsx @@ -13,6 +13,8 @@ export function ImportDropzone() { {({ form }) => ( { hideAlerts();