PrimeNG + NestJS = CRM – part 1

We decided to develop an in-house CRM system. In the course of development, there were interesting moments that I will try to describe in several articles. In the articles I will try to avoid platitudes like: downloaded, unpacked, launched, and look, swagger out of the box. There are already a lot of such articles, as well as videos on YouTube. I will try to share just interesting details that I encountered during development. I’ll run ahead – the system was set up and launched.

1. Why development and not buying a ready-made system

For two reasons. Secondly, because purchased systems over time become so overgrown with additional settings that there is little left of the “box”. And firstly, because (ta-dam!) frameworks have rapidly developed into some kind of platforms in which you have to code a little.

2. Choosing a framework

I wanted to find a framework that already has all the Boiler code that is needed for a business application: menus, sections, charts, users, etc. During the search for such a framework, we paid attention to .Net frameworks https://aspnetboilerplate.com and https://abp.io, in which there are already a lot of things “out of the box”. As far as I understand, both frameworks develop either related teams, or even one team. And teams from Turkey. Again, ta-dam! Here is what happens when there is no oil in the country (either )))), or (((( ). The ASP.NET Boilerplate framework has legacy code from older versions of the .Net Framework. The newer ABP framework does not have legacy, it’s on .Net Core Both frameworks have decent github stars.

I will note video on youtube, Alexey Mersin talks well about ASP.NET Boilerplate, and at 31:41 he shows a nice interface, a menu on the left, there is a color theme, in general, what you need. But perhaps I didn’t understand something, but this interface, which Alexey demonstrates, is a paid version of the framework. The free out-of-the-box version looks dull.

Next came across an interesting library for the front – PrimeNG, it has three branches, under Angular, under React, under Vue. Each branch has a store with themes, there are paid themes, there are free themes. Everything looks very nice, “out of the box” there is everything you need for the front, menus, tabs, buttons, pop-up notifications. And again, ta-dam! Behind PrimeNG is again a team from Turkey, PrimeTek.

As a result, we decided to develop on a bunch of PrimeNG (Angular) + NestJs. Because the front really wants to be on Angular, then there is a desire to save on the expertise of developers, and therefore let TypeScript be both on the front and on the backend.

The disadvantages of Node.js are known:
– TypeScript is still an add-on, I consider the lack of data types in JavaScript to be a disadvantage.
– The node_modules folder will contain several tens (hundreds) of thousands of files written by someone unknown.

2. Logging TypeORM requests

The NestJs framework uses TypeORM to work with the database. The TypeORM library surprised me, it works out well the changes made to the table structure, the replacement of column types, even with data in tables. And in order to view the logs of SQL queries that are generated by TypeORM, you need to add the logging parameter:

TypeOrmModule.forRoot({
type: 'mysql', // ...
entities: [ ContactEntity, ],
logging: true, // Для логирования SQL запросов в консоль
}),

3. Generation of UUID primary key in TypeORM

Boiler columns in tables that should be in every table by default, these are the primary key, creation date, update date. If you declare in TypeORM:

export class ContactEntity {
  @ApiProperty({description: 'Первичный ключ'})
  @PrimaryGeneratedColumn()
  id: string;

@ApiProperty({description: 'Дата создания'})
  @CreateDateColumn()

@ApiProperty({description: 'Дата обновления'})
  @UpdateDateColumn()
  updated: Date;
}

Then in the MySQL database this will turn into:

CREATE TABLE contacts (
id int(11) NOT NULL AUTO_INCREMENT,
created datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id)
);

Everything is fine. But for a business application, I want a UUID primary key, not an integer one.

And if you declare in TypeORM:

export class ContactEntity {
  @ApiProperty({description: 'Первичный ключ'})
  @PrimaryGeneratedColumn('uuid')
  id: string;

 @ApiProperty({description: 'Дата создания'})
  @CreateDateColumn()

 @ApiProperty({description: 'Дата обновления'})
  @UpdateDateColumn()
  updated: Date;
}

Then in the SQL database it will turn into:

CREATE TABLE contacts (
id varchar(36) NOT NULL,
created datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id)
);

That is, the primary key is just a string, with no auto-generated UUID value! At first it seemed strange. But, it turned out that in TypeORM it was deliberately done this way, the UUID is generated in the TypeORM code and the insertion of records comes with the UUID key field already filled in. Because in the case of an auto-generated UUID column, for some kind of insertion, TypeORM would then have to read the inserted records and update them again. This would end up being slower than generating the UUID on the TypeORM side.

4. Notifications in the main menu

In the main menu, next to the section names, you can display an indicator of the number of entries in the section. For example, on the “Orders” menu item, you need to display the order indicator in the “New” status so that the employee immediately pays attention to the fact that new orders have fallen into the system from the site, and these new orders need to be processed faster. To do this, PrimeNG has a badge parameter.

In the AppMenuComponent module, in the menu and sections model, at the “Orders” item, specify the badge and an integer value:

this.model = [
  {
    label: 'Разделы',
      items:[
        {label: 'Контакты', icon: 'pi pi-fw pi-user', routerLink: ['/contact']},
        {label: 'Заказы', icon: 'pi pi-fw pi-table', routerLink: ['/order'], badge: 0},
      ]
  },
]

You will have to update the value at the absolute address of the menu item in the model:

this.model[ 0 ].items[ 1 ].badge = countNewOrder;

roadmap systems

a) You need to transfer the generation of reports in Excel from the front to the backend. Excel files are generated on the backend, and ready-made files are sent to the front end to the user. Why this seems preferable, I will explain in the next article.

b) It is necessary to fasten the job queue. Obviously, some tasks can run indefinitely, so such tasks need to be queued, and then the results should be collected.

c) We need a workflow, for example, the passage of a document, at least in an elementary form, for example, in the form of a guide with the stages of document approval.

d) It is necessary to fasten chats and a chat-bot.

We will show some pieces of what we get on a demo stand – PrimeNG demo.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *