Forced merge: merge ai-dev into master

This commit is contained in:
Flatlogic Bot 2025-04-13 07:22:11 +00:00
commit b8fa163360
19 changed files with 288 additions and 420 deletions

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
node_modules/
*/node_modules/
*/build/
**/node_modules/
**/build/
.DS_Store
.env

View File

@ -24,6 +24,7 @@ module.exports = class ShipmentsDBApi {
state: data.state || null,
customerCharge: data.customerCharge || null,
actualCharge: data.actualCharge || null,
businessname: data.businessname || null,
importHash: data.importHash || null,
createdById: currentUser.id,
updatedById: currentUser.id,
@ -59,6 +60,7 @@ module.exports = class ShipmentsDBApi {
state: item.state || null,
customerCharge: item.customerCharge || null,
actualCharge: item.actualCharge || null,
businessname: item.businessname || null,
importHash: item.importHash || null,
createdById: currentUser.id,
updatedById: currentUser.id,
@ -104,6 +106,9 @@ module.exports = class ShipmentsDBApi {
if (data.actualCharge !== undefined)
updatePayload.actualCharge = data.actualCharge;
if (data.businessname !== undefined)
updatePayload.businessname = data.businessname;
updatePayload.updatedById = currentUser.id;
await shipments.update(updatePayload, { transaction });
@ -299,6 +304,17 @@ module.exports = class ShipmentsDBApi {
};
}
if (filter.businessname) {
where = {
...where,
[Op.and]: Utils.ilike(
'shipments',
'businessname',
filter.businessname,
),
};
}
if (filter.customerChargeRange) {
const [start, end] = filter.customerChargeRange;

View File

@ -0,0 +1,49 @@
module.exports = {
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async up(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
'shipments',
'businessname',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction },
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async down(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.removeColumn('shipments', 'businessname', {
transaction,
});
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

View File

@ -50,6 +50,10 @@ module.exports = function (sequelize, DataTypes) {
type: DataTypes.DECIMAL,
},
businessname: {
type: DataTypes.TEXT,
},
importHash: {
type: DataTypes.STRING(255),
allowNull: true,

View File

@ -9,7 +9,7 @@ const Shipments = db.shipments;
const ProductsData = [
{
productName: 'Andreas Vesalius',
productName: 'John Dalton',
// type code here for "images" field
@ -23,7 +23,7 @@ const ProductsData = [
},
{
productName: 'Thomas Hunt Morgan',
productName: 'Edward Teller',
// type code here for "images" field
@ -37,7 +37,7 @@ const ProductsData = [
},
{
productName: 'Willard Libby',
productName: 'Richard Feynman',
// type code here for "images" field
@ -49,73 +49,29 @@ const ProductsData = [
height: 5,
},
{
productName: 'Theodosius Dobzhansky',
// type code here for "images" field
weight: 4,
length: 25,
width: 12,
height: 6,
},
{
productName: 'Gertrude Belle Elion',
// type code here for "images" field
weight: 5,
length: 30,
width: 15,
height: 8,
},
];
const QuotesData = [
{
carrierName: 'Rudolf Virchow',
carrierName: 'Paul Dirac',
quotePrice: 51.15,
quotePrice: 78.38,
// type code here for "relation_one" field
},
{
carrierName: 'Tycho Brahe',
carrierName: 'Paul Ehrlich',
quotePrice: 62.23,
quotePrice: 99.12,
// type code here for "relation_one" field
},
{
carrierName: 'Karl Landsteiner',
carrierName: 'Michael Faraday',
quotePrice: 48.62,
// type code here for "relation_one" field
},
{
carrierName: 'Jean Baptiste Lamarck',
quotePrice: 52.37,
// type code here for "relation_one" field
},
{
carrierName: 'Sheldon Glashow',
quotePrice: 43.24,
quotePrice: 93.69,
// type code here for "relation_one" field
},
@ -123,123 +79,81 @@ const QuotesData = [
const ShipmentsData = [
{
customer: 'Alfred Wegener',
customer: 'Edward Teller',
phoneNumber: 'Charles Sherrington',
phoneNumber: 'Emil Kraepelin',
address: 'Heike Kamerlingh Onnes',
address2: 'Konrad Lorenz',
zipCode: 'Frederick Gowland Hopkins',
city: 'Nicolaus Copernicus',
state: 'Edward O. Wilson',
// type code here for "relation_many" field
// type code here for "relation_one" field
customerCharge: 30.03,
actualCharge: 95.91,
},
{
customer: 'Hermann von Helmholtz',
phoneNumber: 'Justus Liebig',
address: 'Marie Curie',
address2: 'Alfred Wegener',
zipCode: 'Hans Bethe',
city: 'Enrico Fermi',
state: 'Sigmund Freud',
// type code here for "relation_many" field
// type code here for "relation_one" field
customerCharge: 53.43,
actualCharge: 58.21,
},
{
customer: 'B. F. Skinner',
phoneNumber: 'Gregor Mendel',
address: 'Carl Gauss (Karl Friedrich Gauss)',
address2: 'Alfred Wegener',
zipCode: 'Frederick Sanger',
city: 'Galileo Galilei',
state: 'James Watson',
// type code here for "relation_many" field
// type code here for "relation_one" field
customerCharge: 13.46,
actualCharge: 92.16,
},
{
customer: 'Ernest Rutherford',
phoneNumber: 'Carl Gauss (Karl Friedrich Gauss)',
address: 'John von Neumann',
address2: 'Jonas Salk',
zipCode: 'Leonard Euler',
city: 'Claude Levi-Strauss',
state: 'Pierre Simon de Laplace',
// type code here for "relation_many" field
// type code here for "relation_one" field
customerCharge: 35.87,
actualCharge: 33.48,
},
{
customer: 'Arthur Eddington',
phoneNumber: 'J. Robert Oppenheimer',
address: 'Francis Crick',
address: 'Frederick Sanger',
address2: 'Anton van Leeuwenhoek',
zipCode: 'George Gaylord Simpson',
zipCode: 'Ernst Mayr',
city: 'Claude Levi-Strauss',
city: 'Stephen Hawking',
state: 'Nicolaus Copernicus',
state: 'Max Born',
// type code here for "relation_many" field
// type code here for "relation_one" field
customerCharge: 57.76,
customerCharge: 71.54,
actualCharge: 52.63,
actualCharge: 83.68,
businessname: 'Willard Libby',
},
{
customer: 'Rudolf Virchow',
phoneNumber: 'Comte de Buffon',
address: 'Hans Bethe',
address2: 'Edward Teller',
zipCode: 'Willard Libby',
city: 'Ernst Mayr',
state: 'Joseph J. Thomson',
// type code here for "relation_many" field
// type code here for "relation_one" field
customerCharge: 38.34,
actualCharge: 45.04,
businessname: 'Frederick Sanger',
},
{
customer: 'James Clerk Maxwell',
phoneNumber: 'Charles Sherrington',
address: 'Trofim Lysenko',
address2: 'Werner Heisenberg',
zipCode: 'Charles Darwin',
city: 'Joseph J. Thomson',
state: 'Carl Gauss (Karl Friedrich Gauss)',
// type code here for "relation_many" field
// type code here for "relation_one" field
customerCharge: 43.34,
actualCharge: 10.66,
businessname: 'James Clerk Maxwell',
},
];
@ -278,28 +192,6 @@ async function associateQuoteWithShipment() {
if (Quote2?.setShipment) {
await Quote2.setShipment(relatedShipment2);
}
const relatedShipment3 = await Shipments.findOne({
offset: Math.floor(Math.random() * (await Shipments.count())),
});
const Quote3 = await Quotes.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Quote3?.setShipment) {
await Quote3.setShipment(relatedShipment3);
}
const relatedShipment4 = await Shipments.findOne({
offset: Math.floor(Math.random() * (await Shipments.count())),
});
const Quote4 = await Quotes.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Quote4?.setShipment) {
await Quote4.setShipment(relatedShipment4);
}
}
// Similar logic for "relation_many"
@ -337,28 +229,6 @@ async function associateShipmentWithQuote() {
if (Shipment2?.setQuote) {
await Shipment2.setQuote(relatedQuote2);
}
const relatedQuote3 = await Quotes.findOne({
offset: Math.floor(Math.random() * (await Quotes.count())),
});
const Shipment3 = await Shipments.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Shipment3?.setQuote) {
await Shipment3.setQuote(relatedQuote3);
}
const relatedQuote4 = await Quotes.findOne({
offset: Math.floor(Math.random() * (await Quotes.count())),
});
const Shipment4 = await Shipments.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Shipment4?.setQuote) {
await Shipment4.setQuote(relatedQuote4);
}
}
module.exports = {

View File

@ -41,6 +41,9 @@ router.use(checkCrudPermissions('shipments'));
* state:
* type: string
* default: state
* businessname:
* type: string
* default: businessname
* customerCharge:
* type: integer
@ -338,6 +341,7 @@ router.get(
'zipCode',
'city',
'state',
'businessname',
'customerCharge',
'actualCharge',

View File

@ -61,6 +61,8 @@ module.exports = class SearchService {
'city',
'state',
'businessname',
],
};
const columnsInt = {

View File

@ -59,7 +59,7 @@ const CardProducts = ({
className={`flex items-center ${bgColor} p-6 md:p-0 md:block gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}
>
<Link
href={`/products/products-view/?id=${item.id}`}
href={`/products/products-edit/?id=${item.id}`}
className={'cursor-pointer'}
>
<ImageField

View File

@ -188,6 +188,17 @@ const CardShipments = ({
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Businessname
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{item.businessname}
</div>
</dd>
</div>
</dl>
</li>
))}

View File

@ -119,6 +119,11 @@ const ListShipments = ({
<p className={'text-xs text-gray-500 '}>Actual Charge</p>
<p className={'line-clamp-2'}>{item.actualCharge}</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Businessname</p>
<p className={'line-clamp-2'}>{item.businessname}</p>
</div>
</Link>
<ListActionsPopover
onDelete={onDelete}

View File

@ -37,176 +37,78 @@ export const loadColumns = async (
const hasUpdatePermission = hasPermission(user, 'UPDATE_SHIPMENTS');
return [
{
field: 'customer',
headerName: 'Customer',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'phoneNumber',
headerName: 'Phone Number',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'address',
headerName: 'Address',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'address2',
headerName: 'Address 2',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'zipCode',
headerName: 'Zip Code',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'city',
headerName: 'City',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'state',
headerName: 'State',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'products',
headerName: 'Products',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: false,
sortable: false,
type: 'singleSelect',
valueFormatter: ({ value }) =>
dataFormatter.productsManyListFormatter(value).join(', '),
renderEditCell: (params) => (
<DataGridMultiSelect {...params} entityName={'products'} />
),
},
{
field: 'quote',
headerName: 'Quote',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
sortable: false,
type: 'singleSelect',
getOptionValue: (value: any) => value?.id,
getOptionLabel: (value: any) => value?.label,
valueOptions: await callOptionsApi('quotes'),
valueGetter: (params: GridValueGetterParams) =>
params?.value?.id ?? params?.value,
},
{
field: 'customerCharge',
headerName: 'Customer Charge',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
type: 'number',
},
{
field: 'actualCharge',
headerName: 'Actual Charge',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
type: 'number',
},
{
field: 'actions',
type: 'actions',
minWidth: 30,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
getActions: (params: GridRowParams) => {
return [
<ListActionsPopover
onDelete={onDelete}
itemId={params?.row?.id}
pathEdit={`/shipments/shipments-edit/?id=${params?.row?.id}`}
pathView={`/shipments/shipments-view/?id=${params?.row?.id}`}
key={1}
hasUpdatePermission={hasUpdatePermission}
/>,
];
return [
{
field: 'businessname',
headerName: 'Business Name',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
},
];
{
field: 'customer',
headerName: 'Customer',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'address',
headerName: 'Address',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'state',
headerName: 'State',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'zipCode',
headerName: 'Zip Code',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'customerCharge',
headerName: 'Customer Charge',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
type: 'number',
},
{
field: 'actualCharge',
headerName: 'Actual Charge',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
type: 'number',
},
];
};

View File

@ -7,71 +7,42 @@ const menuAside: MenuAsideItem[] = [
icon: icon.mdiViewDashboardOutline,
label: 'Dashboard',
},
{
href: '/users/users-list',
label: 'Users',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiAccountGroup ? icon.mdiAccountGroup : icon.mdiTable,
permissions: 'READ_USERS',
},
{
href: '/products/products-list',
label: 'Products',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiPackageVariant ? icon.mdiPackageVariant : icon.mdiTable,
permissions: 'READ_PRODUCTS',
},
{
href: '/quotes/quotes-list',
label: 'Quotes',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiCurrencyUsd ? icon.mdiCurrencyUsd : icon.mdiTable,
permissions: 'READ_QUOTES',
},
{
href: '/shipments/shipments-list',
label: 'Shipments',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiTruck ? icon.mdiTruck : icon.mdiTable,
label: 'Shipments',
permissions: 'READ_SHIPMENTS',
},
{
href: '/products/products-list',
icon: icon.mdiPackageVariant ? icon.mdiPackageVariant : icon.mdiTable,
label: 'Products',
permissions: 'READ_PRODUCTS',
},
{ divider: true },
{
href: '/users/users-list',
icon: icon.mdiAccountGroup ? icon.mdiAccountGroup : icon.mdiTable,
label: 'Users',
permissions: 'READ_USERS',
},
{
href: '/roles/roles-list',
icon: icon.mdiShieldAccountVariantOutline ? icon.mdiShieldAccountVariantOutline : icon.mdiTable,
label: 'Roles',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountVariantOutline
? icon.mdiShieldAccountVariantOutline
: icon.mdiTable,
permissions: 'READ_ROLES',
},
{
href: '/permissions/permissions-list',
icon: icon.mdiShieldAccountOutline ? icon.mdiShieldAccountOutline : icon.mdiTable,
label: 'Permissions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountOutline
? icon.mdiShieldAccountOutline
: icon.mdiTable,
permissions: 'READ_PERMISSIONS',
},
{ divider: true },
{
href: '/profile',
label: 'Profile',
icon: icon.mdiAccountCircle,
},
{
href: '/api-docs',
target: '_blank',
label: 'Swagger API',
icon: icon.mdiFileCode,
permissions: 'READ_API_DOCS',
label: 'Profile',
},
];

View File

@ -97,6 +97,8 @@ const QuotesView = () => {
<th>Customer Charge</th>
<th>Actual Charge</th>
<th>Businessname</th>
</tr>
</thead>
<tbody>
@ -130,6 +132,8 @@ const QuotesView = () => {
</td>
<td data-label='actualCharge'>{item.actualCharge}</td>
<td data-label='businessname'>{item.businessname}</td>
</tr>
))}
</tbody>

View File

@ -57,6 +57,8 @@ const EditShipments = () => {
customerCharge: '',
actualCharge: '',
businessname: '',
};
const [initialValues, setInitialValues] = useState(initVals);
@ -177,6 +179,10 @@ const EditShipments = () => {
/>
</FormField>
<FormField label='Businessname'>
<Field name='businessname' placeholder='Businessname' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton type='submit' color='info' label='Submit' />

View File

@ -57,6 +57,8 @@ const EditShipmentsPage = () => {
customerCharge: '',
actualCharge: '',
businessname: '',
};
const [initialValues, setInitialValues] = useState(initVals);
@ -175,6 +177,10 @@ const EditShipmentsPage = () => {
/>
</FormField>
<FormField label='Businessname'>
<Field name='businessname' placeholder='Businessname' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton type='submit' color='info' label='Submit' />

View File

@ -36,6 +36,7 @@ const ShipmentsTablesPage = () => {
{ label: 'Zip Code', title: 'zipCode' },
{ label: 'City', title: 'city' },
{ label: 'State', title: 'state' },
{ label: 'Businessname', title: 'businessname' },
{ label: 'Customer Charge', title: 'customerCharge', number: 'true' },
{ label: 'Actual Charge', title: 'actualCharge', number: 'true' },

View File

@ -54,6 +54,8 @@ const initialValues = {
customerCharge: '',
actualCharge: '',
businessname: '',
};
const ShipmentsNew = () => {
@ -147,6 +149,10 @@ const ShipmentsNew = () => {
/>
</FormField>
<FormField label='Businessname'>
<Field name='businessname' placeholder='Businessname' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton type='submit' color='info' label='Submit' />

View File

@ -36,6 +36,7 @@ const ShipmentsTablesPage = () => {
{ label: 'Zip Code', title: 'zipCode' },
{ label: 'City', title: 'city' },
{ label: 'State', title: 'state' },
{ label: 'Businessname', title: 'businessname' },
{ label: 'Customer Charge', title: 'customerCharge', number: 'true' },
{ label: 'Actual Charge', title: 'actualCharge', number: 'true' },

View File

@ -161,6 +161,11 @@ const ShipmentsView = () => {
<p>{shipments?.actualCharge || 'No data'}</p>
</div>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Businessname</p>
<p>{shipments?.businessname}</p>
</div>
<>
<p className={'block font-bold mb-2'}>Quotes Shipment</p>
<CardBox