@tomei/finance 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/account/account.d.ts +10 -7
  2. package/dist/account/account.js.map +1 -1
  3. package/dist/document/document.d.ts +35 -0
  4. package/dist/document/document.js +115 -0
  5. package/dist/document/document.js.map +1 -0
  6. package/dist/document/entities/document.entity.d.ts +2 -2
  7. package/dist/document/entities/document.entity.js.map +1 -1
  8. package/dist/document/interfaces/document-attr.interface.d.ts +2 -2
  9. package/dist/enum/doc-type.enum.d.ts +7 -0
  10. package/dist/enum/doc-type.enum.js +12 -0
  11. package/dist/enum/doc-type.enum.js.map +1 -0
  12. package/dist/enum/index.d.ts +2 -2
  13. package/dist/enum/index.js +3 -3
  14. package/dist/enum/index.js.map +1 -1
  15. package/dist/finance-company/finance-company.d.ts +8 -3
  16. package/dist/finance-company/finance-company.js +46 -49
  17. package/dist/finance-company/finance-company.js.map +1 -1
  18. package/dist/interfaces/account-system-entity.interface.d.ts +7 -0
  19. package/dist/interfaces/account-system-entity.interface.js +3 -0
  20. package/dist/interfaces/account-system-entity.interface.js.map +1 -0
  21. package/dist/journal-entry/journal-entry.d.ts +3 -1
  22. package/dist/journal-entry/journal-entry.js +12 -0
  23. package/dist/journal-entry/journal-entry.js.map +1 -1
  24. package/dist/tsconfig.tsbuildinfo +1 -1
  25. package/invoice-template/assets/css/style.css +2630 -0
  26. package/invoice-template/assets/css/style.css.map +13 -0
  27. package/invoice-template/assets/css/style.min.css +1 -0
  28. package/invoice-template/assets/img/arrow_bg.svg +12 -0
  29. package/invoice-template/assets/img/coffy_shop_img.svg +19 -0
  30. package/invoice-template/assets/img/header_bg.jpeg +0 -0
  31. package/invoice-template/assets/img/header_bg_2.jpeg +0 -0
  32. package/invoice-template/assets/img/logo.svg +4 -0
  33. package/invoice-template/assets/img/logo_accent.svg +4 -0
  34. package/invoice-template/assets/img/logo_white.svg +4 -0
  35. package/invoice-template/assets/img/qbar.png +0 -0
  36. package/invoice-template/assets/img/shape_1.svg +1 -0
  37. package/invoice-template/assets/img/shape_2.svg +1 -0
  38. package/invoice-template/assets/img/sign.svg +12 -0
  39. package/invoice-template/assets/js/html2canvas.min.js +10379 -0
  40. package/invoice-template/assets/js/jquery.min.js +2 -0
  41. package/invoice-template/assets/js/jspdf.min.js +1 -0
  42. package/invoice-template/assets/js/main.js +48 -0
  43. package/invoice-template/assets/sass/common/_color_variable.scss +12 -0
  44. package/invoice-template/assets/sass/common/_invoice.scss +1802 -0
  45. package/invoice-template/assets/sass/common/_normalize.scss +350 -0
  46. package/invoice-template/assets/sass/common/_typography.scss +178 -0
  47. package/invoice-template/assets/sass/style.scss +12 -0
  48. package/invoice-template/index.html +156 -0
  49. package/invoice-template/sample-invoice.pdf +0 -0
  50. package/migrations/finance-customer-migration.js +33 -33
  51. package/migrations/finance-payment-migration.js +89 -89
  52. package/package.json +3 -1
  53. package/src/account/account.repository.ts +44 -44
  54. package/src/account/account.ts +10 -7
  55. package/src/account/interfaces/account.repository.interface.ts +4 -4
  56. package/src/config.ts +178 -178
  57. package/src/customer/entities/customer.entity.ts +53 -53
  58. package/src/customer/finance-customer.repository.ts +20 -20
  59. package/src/customer/index.ts +15 -15
  60. package/src/customer/interfaces/customer.repository.interface.ts +3 -3
  61. package/src/customer/interfaces/finance-customer-attr.interface.ts +4 -4
  62. package/src/customer/interfaces/finance-customer.repository.interface.ts +3 -3
  63. package/src/document/document.ts +167 -0
  64. package/src/document/entities/document.entity.ts +2 -2
  65. package/src/document/interfaces/document-attr.interface.ts +2 -2
  66. package/src/enum/{document-type.enum.ts → doc-type.enum.ts} +2 -2
  67. package/src/enum/index.ts +2 -2
  68. package/src/finance-company/finance-company.ts +68 -72
  69. package/src/interfaces/account-system-entity.interface.ts +7 -0
  70. package/src/interfaces/index.ts +3 -3
  71. package/src/journal-entry/journal-entry.ts +19 -2
@@ -0,0 +1,167 @@
1
+ import * as util from 'util';
2
+ import * as fs from 'fs';
3
+ import { ObjectBase } from '@tomei/general';
4
+ import {
5
+ Medias,
6
+ InternalMediaDto,
7
+ IMediasRepository,
8
+ CommonService as MediaCommonService,
9
+ MediaType,
10
+ } from '@tomei/media';
11
+ import { DocumentStatus, DocType } from 'src/enum';
12
+ import { DocumentRepository } from './document.repository';
13
+ import { IDocumentAttr } from './interfaces/document-attr.interface';
14
+
15
+ export class Document extends ObjectBase {
16
+ ObjectId: string;
17
+ ObjectName: string;
18
+
19
+ DocNo: string;
20
+ DocType: DocType;
21
+ DocDate: Date;
22
+ SystemCode: string;
23
+ Currency: string;
24
+ Amount: number;
25
+ Description: string;
26
+ Status: DocumentStatus;
27
+ IssuedById: string;
28
+ IssuedToId: string;
29
+ IssuedToType: string;
30
+ AccSystemCode: string;
31
+ PostedToAccYN: string;
32
+ UseAccSystemDocYN: string;
33
+ private DocHTMLFilePath: string;
34
+ private DocPDFFilePath: string;
35
+
36
+ documentRepository: DocumentRepository;
37
+ mediaRepository: IMediasRepository;
38
+ mediaCommonService: MediaCommonService;
39
+
40
+ public get InvoiceInHTML() {
41
+ return (async () => {
42
+ this.DocHTMLFilePath = './invoice-template/index.html';
43
+ const readFileContent = util.promisify(fs.readFile);
44
+ const htmlBuffer = await readFileContent(this.DocHTMLFilePath);
45
+
46
+ const htmlStream: Express.Multer.File = {
47
+ buffer: htmlBuffer,
48
+ fieldname: 'FileStream',
49
+ originalname: 'index.html',
50
+ mimetype: 'text/html',
51
+ size: htmlBuffer.length,
52
+ encoding: '8bit',
53
+ filename: 'sample-invoice.html',
54
+ destination: '',
55
+ path: '',
56
+ stream: null,
57
+ };
58
+
59
+ return htmlStream;
60
+ })();
61
+ }
62
+
63
+ public get InvoiceInPDF() {
64
+ return (async () => {
65
+ this.DocPDFFilePath = './invoice-template/sample-invoice.pdf';
66
+ const readFileContent = util.promisify(fs.readFile);
67
+ const pdfBuffer = await readFileContent(this.DocPDFFilePath);
68
+
69
+ const pdfStream: Express.Multer.File = {
70
+ buffer: pdfBuffer,
71
+ fieldname: 'FileStream',
72
+ originalname: 'sample-invoice.[df]',
73
+ mimetype: 'application/pdf',
74
+ size: pdfBuffer.length,
75
+ encoding: '8bit',
76
+ filename: 'sample-invoice.pdf',
77
+ destination: '',
78
+ path: '',
79
+ stream: null,
80
+ };
81
+
82
+ return pdfStream;
83
+ })();
84
+ }
85
+
86
+ get objectId(): string {
87
+ return this.ObjectId;
88
+ }
89
+ get objectName(): string {
90
+ return this.ObjectName;
91
+ }
92
+
93
+ init(params: IDocumentAttr) {
94
+ this.DocNo = params.DocNo;
95
+ this.DocType = params.DocType;
96
+ this.DocDate = params.DocDate;
97
+ this.SystemCode = params.SystemCode;
98
+ this.Currency = params.Currency;
99
+ this.Amount = params.Amount;
100
+ this.Description = params.Description;
101
+ this.Status = params.Status;
102
+ this.IssuedById = params.IssuedById;
103
+ this.IssuedToId = params.IssuedToId;
104
+ this.IssuedToType = params.IssuedToType;
105
+ this.AccSystemCode = params.AccSystemCode;
106
+ this.PostedToAccYN = params.PostedToAccYN;
107
+ this.UseAccSystemDocYN = params.UseAccSystemDocYN;
108
+ this.DocPDFFilePath = params.DocPDFFilePath;
109
+ this.DocHTMLFilePath = params.DocHTMLFilePath;
110
+ }
111
+
112
+ async generateInvoice(userId?: string): Promise<void> {
113
+ const media: Medias = new Medias(
114
+ this.mediaRepository,
115
+ this.mediaCommonService,
116
+ );
117
+
118
+ const htmlPayload: InternalMediaDto = {
119
+ ObjectId: this.DocNo,
120
+ ObjectType: this.DocType,
121
+ Type: MediaType.Document,
122
+ FileName: `${this.DocType}-${this.DocNo}`,
123
+ FileStream: '',
124
+ FileExtension: 'HTML',
125
+ Title: `${this.DocType}-${this.DocNo}.html`,
126
+ Description: `HTML ${this.DocType}`,
127
+ IsEncryptedYN: 'N',
128
+ };
129
+ await media.postInternal(
130
+ await this.InvoiceInHTML,
131
+ htmlPayload,
132
+ userId ?? 'System',
133
+ );
134
+
135
+ const pdfPayload: InternalMediaDto = {
136
+ ObjectId: this.DocNo,
137
+ ObjectType: this.DocType,
138
+ Type: MediaType.Document,
139
+ FileName: `${this.DocType}-${this.DocNo}`,
140
+ FileStream: '',
141
+ FileExtension: 'PDF',
142
+ Title: `${this.DocType}-${this.DocNo}.pdf`,
143
+ Description: `PDF ${this.DocType}`,
144
+ IsEncryptedYN: 'N',
145
+ };
146
+
147
+ await media.postInternal(
148
+ await this.InvoiceInPDF,
149
+ pdfPayload,
150
+ userId ?? 'System',
151
+ );
152
+
153
+ try {
154
+ const document = await this.documentRepository.findOne({
155
+ where: {
156
+ DocNo: this.DocNo,
157
+ },
158
+ });
159
+
160
+ document.DocHTMLFilePath = this.DocHTMLFilePath;
161
+ document.DocPDFFilePath = this.DocPDFFilePath;
162
+ await document.save();
163
+ } catch (err) {
164
+ console.log(err);
165
+ }
166
+ }
167
+ }
@@ -1,5 +1,5 @@
1
1
  import { Column, DataType, HasMany, Model, Table } from 'sequelize-typescript';
2
- import { DocumentType, DocumentStatus } from '../../enum';
2
+ import { DocType, DocumentStatus } from '../../enum';
3
3
  import { DocumentItemModel } from './document-item.entity';
4
4
 
5
5
  @Table({ tableName: 'finance_Document', timestamps: false })
@@ -15,7 +15,7 @@ export class DocumentModel extends Model {
15
15
  allowNull: false,
16
16
  type: DataType.STRING(30),
17
17
  })
18
- DocType: DocumentType;
18
+ DocType: DocType;
19
19
 
20
20
  @Column({
21
21
  allowNull: false,
@@ -1,8 +1,8 @@
1
- import { DocumentType, DocumentStatus } from '../../enum';
1
+ import { DocType, DocumentStatus } from '../../enum';
2
2
 
3
3
  export class IDocumentAttr {
4
4
  DocNo: string;
5
- DocType: DocumentType;
5
+ DocType: DocType;
6
6
  DocDate: Date;
7
7
  SystemCode: string;
8
8
  Currency: string;
@@ -1,7 +1,7 @@
1
- export enum DocumentType {
1
+ export enum DocType {
2
2
  INVOICE = 'Invoice',
3
3
  DEBIT_NOTE = 'Debit Note',
4
4
  CREDIT_NOTE = 'Credit Note',
5
5
  QUOTATION = 'Quotation',
6
6
  RECEIPT = 'Receipt',
7
- }
7
+ }
package/src/enum/index.ts CHANGED
@@ -2,7 +2,7 @@ import { ClientScopes } from './quick-book-client-scopes.enum';
2
2
  import { PaymentType } from './payment-type.enum';
3
3
  import { PaymentMethod } from './payment-method.enum';
4
4
  import { TransactionTypeOptions } from './transaction-type.enum';
5
- import { DocumentType } from './document-type.enum';
5
+ import { DocType } from './doc-type.enum';
6
6
  import { DocumentStatus } from './document-status.enum';
7
7
 
8
8
  export {
@@ -10,6 +10,6 @@ export {
10
10
  PaymentType,
11
11
  PaymentMethod,
12
12
  TransactionTypeOptions,
13
- DocumentType,
13
+ DocType,
14
14
  DocumentStatus,
15
15
  };
@@ -2,96 +2,92 @@ import { BadRequestException } from '@nestjs/common';
2
2
  import { IAccountSystem } from 'src/interfaces';
3
3
  import { JournalEntry, JournalEntryRepository } from 'src/journal-entry';
4
4
  import { LedgerTransactionRepository } from 'src/ledger-transaction';
5
- import * as uniqid from 'uniqid';
6
5
  import axios from 'axios';
7
- import { JournalEntryModel } from 'src/journal-entry';
8
6
  import { Account } from 'src/account';
7
+ import { CompanyBase, PersonBase } from '@tomei/general';
9
8
 
10
9
  export class FinanceCompany {
11
10
  journalEntryRepository: JournalEntryRepository;
12
11
  ledgerTransactionRepository: LedgerTransactionRepository;
13
-
14
12
  accountingSystem: IAccountSystem;
15
13
 
14
+ private SystemCode: string;
15
+ private AccSystemCode: string;
16
+ private Company: CompanyBase;
17
+ private LoginUser: PersonBase;
18
+
16
19
  constructor(
17
- journalEntryRepository: JournalEntryRepository,
18
- ledgerTransactionRepository: LedgerTransactionRepository,
19
- accountingSystem: IAccountSystem,
20
+ company: CompanyBase,
21
+ systemCode: string,
22
+ accSystemCode: string,
23
+ loginUser: PersonBase,
20
24
  ) {
21
- this.ledgerTransactionRepository = ledgerTransactionRepository;
22
- this.journalEntryRepository = journalEntryRepository;
23
- this.accountingSystem = accountingSystem;
24
- }
25
-
26
- async postJournal(journalEntryId: string, userId: string): Promise<any> {
27
- const journalEntry = new JournalEntry(
28
- this.journalEntryRepository,
29
- this.ledgerTransactionRepository,
30
- );
31
-
32
- if (
33
- journalEntry.CreditTransactions?.length < 1 ||
34
- journalEntry.DebitTransactions?.length < 1
35
- ) {
36
- throw new BadRequestException(
37
- 'There should be at least 1 debit ledger transaction and 1 credit ledger transaction in the journal entry',
38
- );
25
+ this.SystemCode = systemCode;
26
+ this.AccSystemCode = accSystemCode;
27
+ if (company != null && company.ObjectId == '') {
28
+ this.Company = company;
29
+ } else {
30
+ throw new BadRequestException('Company cannot be null');
39
31
  }
40
32
 
41
- if (
42
- journalEntry.CreditTransactions?.length !==
43
- journalEntry.DebitTransactions?.length
44
- ) {
45
- throw new BadRequestException(
46
- 'Credit ledger transaction and debit ledger transaction should the same amount',
47
- );
33
+ if (loginUser != null && loginUser.ObjectId == '') {
34
+ this.LoginUser = loginUser;
35
+ } else {
36
+ throw new BadRequestException('Login user cannot be null');
48
37
  }
38
+ }
49
39
 
50
- const matchingJournalEntry = await this.journalEntryRepository.findOne({
51
- where: {
52
- JournalEntryId: journalEntryId,
53
- },
54
- });
40
+ async postJournal(dbTransaction: any, journalEntry: JournalEntry) {
41
+ try {
42
+ if (
43
+ journalEntry.CreditTransactions?.length < 1 ||
44
+ journalEntry.DebitTransactions?.length < 1
45
+ ) {
46
+ throw new BadRequestException(
47
+ 'There should be at least 1 debit ledger transaction and 1 credit ledger transaction in the journal entry',
48
+ );
49
+ }
55
50
 
56
- matchingJournalEntry.PostedById = userId;
57
- await matchingJournalEntry.save();
51
+ if (
52
+ journalEntry.CreditTransactions?.length !==
53
+ journalEntry.DebitTransactions?.length
54
+ ) {
55
+ throw new BadRequestException(
56
+ 'Credit ledger transaction and debit ledger transaction should the same amount',
57
+ );
58
+ }
58
59
 
59
- const allLedgerTransactions =
60
- await this.ledgerTransactionRepository.findAll();
60
+ const newJournalEntry = await journalEntry.save('test', dbTransaction);
61
61
 
62
- for (const ledgerTransaction of allLedgerTransactions) {
63
- ledgerTransaction.JournalEntryId = journalEntryId;
64
- ledgerTransaction.save();
65
- }
62
+ const allLedgerTransactions =
63
+ await this.ledgerTransactionRepository.findAll();
64
+
65
+ for (const ledgerTransaction of allLedgerTransactions) {
66
+ ledgerTransaction.JournalEntryId = newJournalEntry.JournalEntryId;
67
+ ledgerTransaction.save();
68
+ }
69
+
70
+ await this.accountingSystem.postJournalEntry(newJournalEntry);
66
71
 
67
- journalEntry.init({
68
- JournalEntryId: uniqid(),
69
- Date: new Date(),
70
- Name: '',
71
- Description: '',
72
- PostedById: userId,
73
- PostedToAccSystemYN: 'N',
74
- DatePosted: null,
75
- });
76
-
77
- await this.accountingSystem.postJournalEntry(matchingJournalEntry);
78
-
79
- const payload = {
80
- Action: 'Create',
81
- Activity: 'Post Journal Entry',
82
- Description: `Journal Entry (ID: ${matchingJournalEntry.JournalEntryId}) has been created`,
83
- EntityType: typeof JournalEntryModel,
84
- EntityValueBefore: JSON.stringify({}),
85
- EntityValueAfter: JSON.stringify(matchingJournalEntry),
86
- PerformedById: userId,
87
- PerformedAt: new Date(),
88
- EntityId: matchingJournalEntry.JournalEntryId,
89
- };
90
-
91
- await axios.post(
92
- `${process.env.COMMON_API_URL}/activity-histories`,
93
- payload,
94
- );
72
+ const payload = {
73
+ Action: 'Create',
74
+ Activity: 'Post Journal Entry',
75
+ Description: `Journal Entry (ID: ${newJournalEntry.JournalEntryId}) has been created`,
76
+ EntityType: 'JournalEntry',
77
+ EntityValueBefore: JSON.stringify({}),
78
+ EntityValueAfter: JSON.stringify(newJournalEntry),
79
+ PerformedById: 'test',
80
+ PerformedAt: new Date(),
81
+ EntityId: newJournalEntry.JournalEntryId,
82
+ };
83
+
84
+ await axios.post(
85
+ `${process.env.COMMON_API_URL}/activity-histories`,
86
+ payload,
87
+ );
88
+ } catch (error) {
89
+ throw error;
90
+ }
95
91
  }
96
92
 
97
93
  async createAccount(dbTransaction: any, account: Account) {
@@ -0,0 +1,7 @@
1
+ export interface IAccountSystemEntity {
2
+ AccSystemCode: string;
3
+ PostedToAccSystemYN: string;
4
+ AccSystemRefId: string;
5
+ PostedById: string;
6
+ PostedDateTime: Date;
7
+ }
@@ -1,3 +1,3 @@
1
- import { IAccountSystem } from '../interfaces/account-system.interface';
2
-
3
- export { IAccountSystem };
1
+ import { IAccountSystem } from '../interfaces/account-system.interface';
2
+
3
+ export { IAccountSystem };
@@ -5,6 +5,7 @@ import { JournalEntryRepository } from './journal-entry.repository';
5
5
  import { IJournalEntryAttr } from './interfaces/journal-entry-attr.interface';
6
6
  import { TransactionTypeOptions } from 'src/enum';
7
7
  import { Op } from 'sequelize';
8
+ import { JournalEntryModel } from './entities/journal-entry.entity';
8
9
 
9
10
  export class JournalEntry {
10
11
  JournalEntryId: string;
@@ -22,8 +23,8 @@ export class JournalEntry {
22
23
  private _CreditTransactions: any = null;
23
24
 
24
25
  constructor(
25
- journalEntryRepository: JournalEntryRepository,
26
- ledgerTransactionRepository: LedgerTransactionRepository,
26
+ journalEntryRepository?: JournalEntryRepository,
27
+ ledgerTransactionRepository?: LedgerTransactionRepository,
27
28
  ) {
28
29
  this.ledgerTransactionRepository = ledgerTransactionRepository;
29
30
  this.journalEntryRepository = journalEntryRepository;
@@ -103,6 +104,22 @@ export class JournalEntry {
103
104
  return await this.journalEntryRepository.create(this.getData);
104
105
  }
105
106
 
107
+ async save(userId: string, dbTransaction?: any): Promise<JournalEntryModel> {
108
+ const data = await this.journalEntryRepository.create(
109
+ {
110
+ JournalEntryId: this.JournalEntryId,
111
+ Date: this.Date,
112
+ Name: this.Name,
113
+ Description: this.Description,
114
+ PostedById: userId,
115
+ PostedToAccSystemYN: this.PostedToAccSystemYN,
116
+ DatePosted: this.DatePosted,
117
+ },
118
+ dbTransaction,
119
+ );
120
+ return data;
121
+ }
122
+
106
123
  async newLedgerTransaction({
107
124
  transactionType,
108
125
  }: ILedgerTransactionTypeOptionsAttr): Promise<any> {