Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | 1x 1x 1x 1x 1x 1x 111x 111x 111x 111x | import {Getter, inject} from '@loopback/core';
import {BelongsToAccessor, Options, repository} from '@loopback/repository';
import {FlowReferenceRepository, FormRepository} from '.';
import {LogChainDataSource} from '../datasources';
import {FlowAction, FlowActionRelations, Form} from '../models';
import {BaseCrudRepository} from './base-crud.repository.base';
import { AnyObject } from 'loopback-datasource-juggler';
export class FlowActionRepository extends BaseCrudRepository<
FlowAction,
typeof FlowAction.prototype.id,
FlowActionRelations
> {
public readonly form: BelongsToAccessor<Form, typeof FlowAction.prototype.id>;
constructor(
@inject('datasources.logchain') dataSource: LogChainDataSource,
@repository.getter('FlowReferenceRepository')
protected flow_ref_getter: Getter<FlowReferenceRepository>,
@repository.getter('FormRepository')
protected formRepositoryGetter: Getter<FormRepository>,
) {
super(FlowAction, dataSource);
this.form = this.createBelongsToAccessor('form', formRepositoryGetter);
}
/**
* Find actions by journey id.
* @param flow_id The flow id.
* @param step_id The step id.
*/
async findActionsByJourneyId(
flow_id: number,
step_id: number,
): Promise<FlowAction[]> {
const actions = await this.execute(
`SELECT
fdc.ID,
MAX(actions."order") as order,
CASE
WHEN fdc.form_id IS NULL THEN
0
ELSE fdc.form_id
END form_id,
CASE
WHEN fdc.title IS NOT NULL THEN
fdc.title
WHEN fdc.title IS NULL THEN
CASE
WHEN fdc.form_id IS NOT NULL THEN
f."name"
END
END form_name,
CASE
WHEN fdc.form_id = 0 THEN
'Document'
WHEN fdc.form_id <> 0 THEN
'Form'
END form_type,
fdc.flow_persona_id AS flow_persona_id,
fdp.name AS flow_persona_name,
fdc.form_data
FROM
flows_action AS fdc
LEFT JOIN forms AS f ON fdc.form_id = f.ID
INNER JOIN actions ON actions.form_id = fdc.form_id
LEFT JOIN flows_persona AS fdp ON fdp.ID = fdc.flow_persona_id
WHERE
fdc.flow_id = $1
AND fdc.flow_journey_point_id = $2
GROUP BY
fdc.ID,
fdp.name,
f.name
ORDER BY "order";`,
[flow_id, step_id],
);
return actions as FlowAction[];
}
/**
* Override deleteById to remove all reference documents if the journey points don't have any action.
* @param id The flow persona id.
* @param options The options.
*/
async deleteById(
id: typeof FlowAction.prototype.id,
options?: Options,
): Promise<void> {
await super.deleteById(id, options);
if (options?.flow_id && options?.journey_point_id) {
const {count: rest_action} = await this.count(
{
flow_id: options?.flow_id,
flow_journey_point_id: options?.journey_point_id,
},
options,
);
// if current journey points have atleast on action. keep reference documents
if (rest_action > 0) {
return;
}
// otherwise, delete all.
const repo = await this.flow_ref_getter();
await repo.deleteAll(
{
flow_id: options?.flow_id,
flow_journey_point_id: options?.journey_point_id,
},
options,
);
}
}
/**
* Cancels actions by container orders.
*
* @param {number} flow_id - The ID of the flow.
* @param {number[]} container_orders - The array of container orders.
* @param {Options} options - The options for the cancellation.
* @return {Promise<void>} A promise that resolves when the cancellation is complete.
*/
async cancelActionsByContainerOrders(flow_id: number, container_orders: number[], options?: Options): Promise<void> {
await this.execute(`SELECT cancel_actions_of_flow($1, $2);`, [flow_id, container_orders], options);
}
/**
* Retrieves the total number of actions and the number of cancelled actions for a given flow ID.
*
* @param {number} flow_id - The ID of the flow.
* @param {Options} options - Optional parameters for the database query.
* @returns {Promise<AnyObject>} A promise that resolves to an object containing the total number
* of actions and the number of cancelled actions.
*/
async getTotalAndCancelledActionsByFlowId(flow_id: number, options?: Options): Promise<AnyObject>
{
const resl = await this.execute(`
SELECT
COUNT(id) total_actions,
COUNT(CASE WHEN status_name = 'Cancelled' THEN 1 ELSE NULL END) cancelled_actions
FROM actions_data_view
WHERE flow_id = $1 AND container_no <> '';`, [flow_id], options);
return resl.length ? resl[0] : { total_actions: 0, cancelled_actions: 0 };
}
/**
* Retrieves the cancelled actions for a given flow ID and containers.
*
* @param {number} flow_id - The ID of the flow.
* @param {string[]} containers - The list of containers.
* @param {Options} [options] - Optional parameters for the database query.
* @return {Promise<AnyObject>} A promise that resolves to an object containing the cancelled actions.
*/
async getCancelledActionsByFlowIdAndContainers(flow_id: number, containers: string[], options?: Options): Promise<AnyObject>
{
return this.execute(`
SELECT
fa.id, fa.flow_id, fa.company_id,
CASE WHEN form_id = 0 THEN fa.title ELSE f."name" END action_name,
status_name
FROM flows_action fa
INNER JOIN flows_persona fp ON fp.flow_id = fa.flow_id AND fp.needed_info ->> 'container_no'::text IS NOT NULL
LEFT JOIN actions_data_view adv ON adv.flow_action_id = fa.id
LEFT JOIN forms f ON f.id = fa.form_id
WHERE fa.flow_id = $1 AND (fp.needed_info ->> 'container_no'::text)::jsonb ->> (fa.container_order - 1) = ANY($2) AND status_name = 'Cancelled';`, [flow_id, containers], options);
}
/**
* Update form data based on container number if LoadWeight is present.
*
* @param {number} flow_id - The ID of the flow.
* @param {number} container_number - The container number.
* @param {AnyObject} form_data - The form data.
* @param {Options} [options] - Optional parameters for the execution.
* @return {Promise<void>} A promise that resolves with void.
*/
async updateFormDataByContainerNumber(flow_id: number, container_number: number, form_data: AnyObject, options?: Options): Promise<void>
{
if (form_data?.LoadWeight) {
// Update expected_weight
await this.execute(`
UPDATE flows_action fa
SET form_data = form_data || jsonb_build_object('expected_weight', $3::FLOAT)
WHERE flow_id = $1
AND (container_order = $2 OR container_order IS NULL)
AND fa.form_data ->> 'expected_weight' IS NOT NULL;`
, [flow_id, container_number, form_data?.LoadWeight ?? 0], options
);
}
}
/**
* Updates the form data with a new container's booking reference for a specific flow.
*
* @param {number} flow_id - The ID of the flow.
* @param {string} newContainer - The new container to append the booking reference.
* @param {AnyObject} ram_order - The RAM order object containing VesselData.
* @param {Options} options - Optional parameters for the database query.
* @return {Promise<void>} A promise that resolves when the update is complete.
*/
async appendContainerToBookingRef(flow_id: number, newContainer: string, ram_order: AnyObject, options?: Options): Promise<void>{
if (ram_order?.VesselData) {
const bookingRef = Object.values(ram_order.VesselData as AnyObject)[0][newContainer];
if (bookingRef) {
await this.execute(`
UPDATE flows_action fa
SET form_data = jsonb_set(
form_data,
'{vessel_booking_ref}',
form_data->'vessel_booking_ref' || jsonb_build_object($2, $3),
true
)
WHERE flow_id = $1
AND form_data->'vessel_booking_ref' IS NOT NULL;`
, [flow_id, newContainer, bookingRef], options
);
}
}
}
}
|