Tag can always be reassigned
MODIFY
src/assets/server/rest/v1/docs/e-mobility-oas.json
src/assets/server/rest/v1/docs/e-mobility-oas.json
}
}
},
- "/api/transactions/status/unassigned/count": {
- "get": {
- "security": [
- {
- "bearerAuth": []
- }
- ],
- "description": "Count unassigned Transactions",
- "parameters": [
- {
- "$ref": "#/components/parameters/TagID"
- }
- ],
- "tags": [
- "Transactions"
- ],
- "responses": {
- "200": {
- "description": "Return unassigned Transactions count",
- "content": {
- "text/plain": {
- "example": 42
- }
- }
- },
- "401": {
- "$ref": "#/components/responses/UnauthorizedError"
- },
- "403": {
- "$ref": "#/components/responses/ForbiddenError"
- },
- "500": {
- "$ref": "#/components/responses/BackendError"
- }
- }
- }
- },
"/api/transactions/{id}": {
"get": {
"security": [
}
}
},
- "/api/transactions/action/assign-user": {
- "put": {
- "security": [
- {
- "bearerAuth": []
- }
- ],
- "description": "Assign Transactions to a user",
- "parameters": [
- {
- "in": "query",
- "name": "TagID",
- "description": "Tag ID",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "in": "query",
- "name": "UserID",
- "description": "User ID",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
- ],
- "tags": [
- "Transactions"
- ],
- "responses": {
- "200": {
- "description": "Transactions successfully assigned",
- "content": {
- "application/json": {
- "example": {
- "status": "Success"
- }
- }
- }
- },
- "401": {
- "$ref": "#/components/responses/UnauthorizedError"
- },
- "403": {
- "$ref": "#/components/responses/ForbiddenError"
- },
- "500": {
- "$ref": "#/components/responses/BackendError"
- }
- }
- }
- },
"/api/transactions/action/export": {
"get": {
"security": [

MODIFY
src/server/rest/CentralRestServerService.ts
src/server/rest/CentralRestServerService.ts
@@ -130,7 +130,6 @@ class RequestMapper {
[ServerAction.TRANSACTIONS_ACTIVE]: TransactionService.handleGetTransactionsActive.bind(this),
[ServerAction.TRANSACTIONS_IN_ERROR]: TransactionService.handleGetTransactionsInError.bind(this),
[ServerAction.TRANSACTION_YEARS]: TransactionService.handleGetTransactionYears.bind(this),
- [ServerAction.UNASSIGNED_TRANSACTIONS_COUNT]: TransactionService.handleGetUnassignedTransactionsCount.bind(this),
[ServerAction.TRANSACTION_OCPI_CDR_EXPORT]: TransactionService.handleExportTransactionOcpiCdr.bind(this),
[ServerAction.CHARGING_STATION_CONSUMPTION_STATISTICS]: StatisticService.handleGetChargingStationConsumptionStatistics.bind(this),
[ServerAction.CHARGING_STATION_USAGE_STATISTICS]: StatisticService.handleGetChargingStationUsageStatistics.bind(this),
@@ -178,7 +177,6 @@ class RequestMapper {
[ServerAction.SITE_USER_ADMIN]: SiteService.handleUpdateSiteUserAdmin.bind(this),
[ServerAction.SITE_OWNER]: SiteService.handleUpdateSiteOwner.bind(this),
[ServerAction.TRANSACTION_SOFT_STOP]: TransactionService.handleTransactionSoftStop.bind(this),
- [ServerAction.ASSIGN_TRANSACTIONS_TO_USER]: TransactionService.handleAssignTransactionsToUser.bind(this),
[ServerAction.SETTING_UPDATE]: SettingService.handleUpdateSetting.bind(this),
[ServerAction.OCPI_ENDPOINT_UPDATE]: OCPIEndpointService.handleUpdateOcpiEndpoint.bind(this),
[ServerAction.OCPI_ENDPOINT_REGISTER]: OCPIEndpointService.handleRegisterOcpiEndpoint.bind(this),

MODIFY
src/server/rest/v1/router/api/TransactionRouter.ts
src/server/rest/v1/router/api/TransactionRouter.ts
@@ -17,7 +17,6 @@ export default class TransactionRouter {
this.buildRouteTransactionsCompleted();
this.buildRouteTransactionsActive();
this.buildRouteTransactionsInError();
- this.buildRouteTransactionsUnassignedCount();
this.buildRouteTransactionsGetRefund();
this.buildRouteTransaction();
this.buildRouteTransactionConsumption();
@@ -27,7 +26,6 @@ export default class TransactionRouter {
this.buildRouteExportTransactionCDR();
this.buildRouteTransactionSoftStop();
this.buildRouteTransactionsRefund();
- this.buildRouteTransactionsAssignUser();
this.buildRouteTransactionsExport();
this.buildRouteSynchronizeRefundedTransactions();
this.buildRouteTransactionsRefundReports();
@@ -59,12 +57,6 @@ export default class TransactionRouter {
});
}
- protected buildRouteTransactionsUnassignedCount(): void {
- this.router.get(`/${ServerRoute.REST_TRANSACTIONS_UNASSIGNED_COUNT}`, async (req: Request, res: Response, next: NextFunction) => {
- await RouterUtils.handleServerAction(TransactionService.handleGetUnassignedTransactionsCount.bind(this), ServerAction.UNASSIGNED_TRANSACTIONS_COUNT, req, res, next);
- });
- }
-
protected buildRouteTransactionsGetRefund(): void {
this.router.get(`/${ServerRoute.REST_TRANSACTIONS_REFUND}`, async (req: Request, res: Response, next: NextFunction) => {
await RouterUtils.handleServerAction(TransactionService.handleGetTransactionsToRefund.bind(this), ServerAction.TRANSACTIONS_TO_REFUND, req, res, next);
@@ -126,12 +118,6 @@ export default class TransactionRouter {
});
}
- protected buildRouteTransactionsAssignUser(): void {
- this.router.put(`/${ServerRoute.REST_TRANSACTIONS_ASSIGN_USER}`, async (req: Request, res: Response, next: NextFunction) => {
- await RouterUtils.handleServerAction(TransactionService.handleAssignTransactionsToUser.bind(this), ServerAction.ASSIGN_TRANSACTIONS_TO_USER, req, res, next);
- });
- }
-
protected buildRouteTransactionsExport(): void {
this.router.get(`/${ServerRoute.REST_TRANSACTIONS_EXPORT}`, async (req: Request, res: Response, next: NextFunction) => {
await RouterUtils.handleServerAction(TransactionService.handleExportTransactions.bind(this), ServerAction.TRANSACTIONS_EXPORT, req, res, next);

MODIFY
src/server/rest/v1/service/TagService.ts
src/server/rest/v1/service/TagService.ts
@@ -162,19 +162,6 @@ export default class TagService {
action: action
});
}
- // Check if Tag has been already used
- const transactions = await TransactionStorage.getTransactions(req.tenant,
- { tagIDs: [filteredRequest.id.toUpperCase()], hasUserID: true }, Constants.DB_PARAMS_SINGLE_RECORD, ['id']);
- if (!Utils.isEmptyArray(transactions.result)) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.TAG_HAS_TRANSACTIONS,
- message: `Tag with ID '${filteredRequest.id}' has been used in previous transactions`,
- module: MODULE_NAME, method: 'handleCreateTag',
- user: req.user,
- action: action
- });
- }
if (filteredRequest.userID) {
// Get User
await UtilsService.checkAndGetUserAuthorization(req.tenant, req.user, filteredRequest.userID,
@@ -259,19 +246,6 @@ export default class TagService {
action: action
});
}
- // Check if Tag has been already used
- const transactions = await TransactionStorage.getTransactions(req.tenant,
- { tagIDs: [tag.id.toUpperCase()] }, Constants.DB_PARAMS_SINGLE_RECORD, ['id']);
- if (!Utils.isEmptyArray(transactions.result)) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.TAG_HAS_TRANSACTIONS,
- message: `Tag with ID '${filteredRequest.id}' has been used in previous transactions`,
- module: MODULE_NAME, method: 'handleAssignTag',
- user: req.user,
- action: action
- });
- }
// Get User
const user = await UtilsService.checkAndGetUserAuthorization(req.tenant, req.user, filteredRequest.userID,
Action.READ, ServerAction.TAG_ASSIGN);
@@ -358,7 +332,7 @@ export default class TagService {
UtilsService.checkIfUserTagIsValid(filteredRequest, req);
// Check and Get Tag
const tag = await UtilsService.checkAndGetTagAuthorization(req.tenant, req.user, filteredRequest.id, Action.UPDATE, action,
- filteredRequest, { withNbrTransactions: true, withUser: true }, true);
+ filteredRequest, { withUser: true }, true);
if (filteredRequest.userID) {
await UtilsService.checkAndGetUserAuthorization(req.tenant, req.user, filteredRequest.userID,
Action.READ, ServerAction.TAG_UPDATE);
@@ -381,16 +355,6 @@ export default class TagService {
let formerTagDefault: boolean;
// Cannot change the User of a Badge that has already some transactions
if (tag.userID !== filteredRequest.userID) {
- if (tag.transactionsCount > 0) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.TAG_HAS_TRANSACTIONS,
- message: `Cannot change the User of the Tag ID '${tag.id}' which has '${tag.transactionsCount}' transaction(s)`,
- module: MODULE_NAME, method: 'handleUpdateTag',
- user: req.user,
- action: action
- });
- }
formerTagUserID = tag.userID;
formerTagDefault = tag.default;
}

MODIFY
src/server/rest/v1/service/TransactionService.ts
src/server/rest/v1/service/TransactionService.ts
@@ -291,92 +291,6 @@ export default class TransactionService {
next();
}
- public static async handleGetUnassignedTransactionsCount(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- // Check Auth
- if (!await Authorizations.canUpdateTransaction(req.user)) {
- throw new AppAuthError({
- errorCode: HTTPAuthError.FORBIDDEN,
- user: req.user,
- action: Action.UPDATE, entity: Entity.TRANSACTION,
- module: MODULE_NAME, method: 'handleGetUnassignedTransactionsCount'
- });
- }
- // Filter
- const filteredRequest = TransactionValidator.getInstance().validateTransactionsUnassignedCountReq(req.query);
- // Get the user
- const tag = await TagStorage.getTag(req.tenant, filteredRequest.TagID);
- UtilsService.assertObjectExists(action, tag, `Tag ID '${filteredRequest.TagID}' does not exist`,
- MODULE_NAME, 'handleAssignTransactionsToUser', req.user);
- // Get unassigned transactions
- const count = await TransactionStorage.getUnassignedTransactionsCount(req.tenant, tag.id);
- // Return
- res.json(count);
- next();
- }
-
- public static async handleAssignTransactionsToUser(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
- // Check auths
- if (!await Authorizations.canUpdateTransaction(req.user)) {
- throw new AppAuthError({
- errorCode: HTTPAuthError.FORBIDDEN,
- user: req.user,
- action: Action.UPDATE, entity: Entity.TRANSACTION,
- module: MODULE_NAME, method: 'handleAssignTransactionsToUser'
- });
- }
- // Filter
- const filteredRequest = TransactionValidator.getInstance().validateTransactionsUserAssignReq(req.query);
- // Check
- if (!filteredRequest.TagID) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.GENERAL_ERROR,
- message: 'Tag ID must be provided',
- module: MODULE_NAME, method: 'handleAssignTransactionsToUser',
- user: req.user, action: action
- });
- }
- if (!filteredRequest.UserID) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.GENERAL_ERROR,
- message: 'User ID must be provided',
- module: MODULE_NAME, method: 'handleAssignTransactionsToUser',
- user: req.user, action: action
- });
- }
- // Get the user
- const user: User = await UserStorage.getUser(req.tenant, filteredRequest.UserID);
- UtilsService.assertObjectExists(action, user, `User ID '${filteredRequest.UserID}' does not exist`,
- MODULE_NAME, 'handleAssignTransactionsToUser', req.user);
- // Get the tag
- const tag = await TagStorage.getTag(req.tenant, filteredRequest.TagID);
- UtilsService.assertObjectExists(action, tag, `Tag ID '${filteredRequest.TagID}' does not exist`,
- MODULE_NAME, 'handleAssignTransactionsToUser', req.user);
- if (!user.issuer) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.GENERAL_ERROR,
- message: 'User not issued by the organization',
- module: MODULE_NAME, method: 'handleAssignTransactionsToUser',
- user: req.user, action: action
- });
- }
- if (!tag.issuer) {
- throw new AppError({
- source: Constants.CENTRAL_SERVER,
- errorCode: HTTPError.GENERAL_ERROR,
- message: 'Tag not issued by the organization',
- module: MODULE_NAME, method: 'handleAssignTransactionsToUser',
- user: req.user, action: action
- });
- }
- // Assign
- await TransactionStorage.assignTransactionsToUser(req.tenant, user.id, tag.id);
- res.json(Constants.REST_RESPONSE_SUCCESS);
- next();
- }
-
public static async handleDeleteTransaction(action: ServerAction, req: Request, res: Response, next: NextFunction): Promise<void> {
// Filter
const transactionId = TransactionValidator.getInstance().validateTransactionGetReq(req.query).ID;

MODIFY
src/storage/mongodb/TransactionStorage.ts
src/storage/mongodb/TransactionStorage.ts
@@ -288,39 +288,6 @@ export default class TransactionStorage {
await Logging.traceEnd(tenant.id, MODULE_NAME, 'saveTransactionRefundData', uniqueTimerID, refundData);
}
- public static async assignTransactionsToUser(tenant: Tenant, userID: string, tagID: string): Promise<void> {
- // Debug
- const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'assignTransactionsToUser');
- // Assign transactions
- await global.database.getCollection(tenant.id, 'transactions').updateMany({
- $and: [
- { 'userID': null },
- { 'tagID': tagID }
- ]
- }, {
- $set: {
- userID: DatabaseUtils.convertToObjectID(userID)
- }
- });
- // Debug
- await Logging.traceEnd(tenant.id, MODULE_NAME, 'assignTransactionsToUser', uniqueTimerID);
- }
-
- public static async getUnassignedTransactionsCount(tenant: Tenant, tagID: string): Promise<number> {
- // Debug
- const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getUnassignedTransactionsCount');
- // Get the number of unassigned transactions
- const unassignedCount = await global.database.getCollection<Transaction>(tenant.id, 'transactions').find({
- $and: [
- { 'userID': null },
- { 'tagID': tagID }
- ]
- }).count();
- // Debug
- await Logging.traceEnd(tenant.id, MODULE_NAME, 'getUnassignedTransactionsCount', uniqueTimerID);
- return unassignedCount;
- }
-
public static async getTransactionYears(tenant: Tenant): Promise<Date[]> {
// Debug
const uniqueTimerID = Logging.traceStart(tenant.id, MODULE_NAME, 'getTransactionYears');

MODIFY
src/types/HTTPError.ts
src/types/HTTPError.ts
@@ -25,7 +25,6 @@ export enum HTTPError {
USER_EULA_ERROR = 520,
USER_NO_BADGE_ERROR = 570,
- TAG_HAS_TRANSACTIONS = 575,
TAG_ALREADY_EXIST_ERROR = 576,
TAG_VISUAL_ID_ALREADY_EXIST_ERROR = 577,
TAG_VISUAL_ID_DOES_NOT_MATCH_TAG_ERROR = 578,

MODIFY
src/types/Server.ts
src/types/Server.ts
@@ -54,7 +54,6 @@ export enum ServerAction {
TRANSACTION_SOFT_STOP = 'TransactionSoftStop',
TRANSACTION_DELETE = 'TransactionDelete',
TRANSACTIONS_DELETE = 'TransactionsDelete',
- ASSIGN_TRANSACTIONS_TO_USER = 'AssignTransactionsToUser',
UPDATE_TRANSACTION = 'UpdateTransaction',
LOGGINGS = 'Loggings',
@@ -302,7 +301,6 @@ export enum ServerAction {
TRANSACTIONS_ACTIVE = 'TransactionsActive',
TRANSACTIONS_IN_ERROR = 'TransactionsInError',
TRANSACTION_YEARS = 'TransactionYears',
- UNASSIGNED_TRANSACTIONS_COUNT = 'UnassignedTransactionsCount',
TRANSACTION = 'Transaction',
TRANSACTIONS = 'Transactions',
TRANSACTION_CONSUMPTION = 'TransactionConsumption',
@@ -510,7 +508,6 @@ export enum ServerRoute {
REST_TRANSACTIONS_IN_ERROR = 'transactions/status/in-error',
REST_TRANSACTIONS_ACTIVE = 'transactions/status/active',
REST_TRANSACTIONS_COMPLETED = 'transactions/status/completed',
- REST_TRANSACTIONS_UNASSIGNED_COUNT = 'transactions/status/unassigned/count',
REST_TRANSACTION = 'transactions/:id',
REST_TRANSACTIONS_EXPORT = 'transactions/action/export',
REST_TRANSACTION_CDR = 'transactions/:id/ocpi/cdr',
@@ -520,7 +517,6 @@ export enum ServerRoute {
REST_TRANSACTIONS_REFUND_ACTION = 'transactions/action/refund',
REST_TRANSACTIONS_REFUND = 'transactions/status/refund',
REST_TRANSACTIONS_REFUND_EXPORT = 'transactions/status/refund/export',
- REST_TRANSACTIONS_ASSIGN_USER = 'transactions/action/assign-user',
REST_TRANSACTIONS_SYNCHRONIZE_REFUNDED = 'transactions/status/refund/synchronize',
REST_TRANSACTIONS_REFUND_REPORTS = 'transactions/status/refund/reports',

Tag can always be reassigned