/// <summary> /// Executes the workflow to deactivate a device. /// </summary> /// <param name="request">The deactivate device request.</param> /// <returns>The response.</returns> protected override NullResponse Process(DeactivateDeviceRequest request) { ThrowIf.Null(request, "request"); GetCurrentTerminalIdDataRequest dataRequest = new GetCurrentTerminalIdDataRequest(); string terminalId = this.Context.Execute <SingleEntityDataServiceResponse <string> >(dataRequest).Entity; // Slect all shifts. IList <Shift> shifts = ShiftDataDataServiceHelper.GetAllOpenedShiftsOnTerminal(this.Context, this.Context.GetPrincipal().ChannelId, terminalId, true); if (shifts.HasMultiple()) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_TerminalHasAnOpenShift); } var serviceRequest = new DeactivateDeviceServiceRequest(this.Context.GetPrincipal().DeviceNumber, terminalId, this.Context.GetPrincipal().UserId, this.Context.GetPrincipal().DeviceToken); DeactivateDeviceServiceResponse deactivationResponse = this.Context.Execute <DeactivateDeviceServiceResponse>(serviceRequest); if (!string.IsNullOrWhiteSpace(deactivationResponse.DeactivationResult.ErrorMessage)) { throw new DeviceAuthenticationException(SecurityErrors.Microsoft_Dynamics_Commerce_Runtime_DeviceDeactivationFailed, deactivationResponse.DeactivationResult.ErrorMessage); } // Log off the user. var userLogOffRequest = new UserLogOffRequest { StaffId = this.Context.GetPrincipal().UserId, LogOnConfiguration = this.Context.GetPrincipal().LogOnConfiguration }; AuthenticationHelper.LogOff(this.Context, userLogOffRequest); return(new NullResponse()); }
/// <summary> /// Executes the create shift staging workflow. /// </summary> /// <param name="request">The new Shift request.</param> /// <returns>The new Shift response.</returns> protected override ChangeShiftStatusResponse Process(ChangeShiftStatusRequest request) { ThrowIf.Null(request, "request"); ThrowIf.Null(request.ShiftTerminalId, "request.ShiftTerminalId"); if (this.Context.GetTerminal() != null) { request.TerminalId = this.Context.GetTerminal().TerminalId; } EmployeePermissions permissions = EmployeePermissionHelper.GetEmployeePermissions(this.Context, this.Context.GetPrincipal().UserId); bool includeSharedShifts = permissions.HasManagerPrivileges || permissions.AllowManageSharedShift || permissions.AllowUseSharedShift; var staffId = this.Context.GetPrincipal().UserId; var terminalId = request.ShiftTerminalId; var shifts = ShiftDataDataServiceHelper.GetShifts( this.Context, this.Context.GetPrincipal().ChannelId, terminalId, request.ShiftId, includeSharedShifts); Shift shift = ShiftDataDataServiceHelper.FilterShifts(shifts, terminalId, staffId).FirstOrDefault(); if (shift == null) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ObjectNotFound, "There is no shift with the given identifier."); } ShiftTransitionHelper shiftTransitionHelper = new ShiftTransitionHelper(this.Context, request); // Validate if the change of shift status can be performed shiftTransitionHelper.TransitShiftStatus(shift); shift.StatusDateTime = this.Context.GetNowInChannelTimeZone(); UpdateShiftStagingTableDataRequest dataServiceRequest = new UpdateShiftStagingTableDataRequest(shift); request.RequestContext.Runtime.Execute <NullResponse>(dataServiceRequest, this.Context); this.SaveTransactionLog(shift, request.TransactionId); if (request.ToStatus == ShiftStatus.Closed) { this.PurgeSalesTransactionData(request.RequestContext); } return(new ChangeShiftStatusResponse(shift)); }
/// <summary> /// Validates whether the shift can be resumed. /// </summary> /// <param name="request">The request.</param> /// <param name="shift">The shift.</param> private void ValidateCanResumeShift(ResumeShiftRequest request, Shift shift) { if (shift == null) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ObjectNotFound, "There is no shift with the given identifier."); } if (shift.Status != ShiftStatus.Suspended) { // we cannot resume an opened shift, only use it throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidRequest, "Cannot resume a non-suspended shift. If the shift is open, try using it instead."); } if (!this.Permissions.HasManagerPrivileges) { if (shift.IsShared && !this.Permissions.AllowManageSharedShift) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_EmployeeNotAllowedManageSharedShift, "Employee not allowed to manage shared shift."); } // if it is not shared shift and if the user is not a manager, the user can only resume a shift that she/he owns or have permissions to if (!shift.IsShared && !string.Equals(shift.StaffId, this.Context.GetPrincipal().UserId, StringComparison.OrdinalIgnoreCase) && !string.Equals(shift.CurrentStaffId, this.Context.GetPrincipal().UserId, StringComparison.OrdinalIgnoreCase) && !this.Permissions.AllowMultipleShiftLogOn) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidRequest, "The user does not have permission to resume shift."); } } IList <Shift> openShiftsOnStore = ShiftDataDataServiceHelper.GetAllStoreShiftsWithStatus(this.Context, this.Context.GetPrincipal().ChannelId, ShiftStatus.Open, request.QueryResultSettings, true); bool cannotOpenShift = openShiftsOnStore.Any(openShift => { bool cashDrawerHasOpenShift = string.Equals(openShift.CashDrawer, request.CashDrawer, StringComparison.OrdinalIgnoreCase); return((openShift.IsShared || string.Equals(openShift.CurrentTerminalId, request.TerminalId, StringComparison.OrdinalIgnoreCase)) && cashDrawerHasOpenShift); }); if (cannotOpenShift) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CashDrawerHasAnOpenShift, "There is an open shift on the current cash drawer."); } }
/// <summary> /// Validates whether employee can open shifts. /// </summary> /// <param name="request">The create shift request.</param> private void ValidateCanOpenShift(CreateShiftRequest request) { IList <Shift> shifts = ShiftDataDataServiceHelper.GetAllStoreShiftsWithStatus(this.Context, this.Context.GetPrincipal().ChannelId, ShiftStatus.Open, new QueryResultSettings(PagingInfo.AllRecords), true); if (!this.Context.GetPrincipal().IsInRole(AuthenticationHelper.ManagerPrivilegies)) { EmployeePermissions employeePermission = EmployeePermissionHelper.GetEmployeePermissions(this.Context, this.Context.GetPrincipal().UserId); if (employeePermission != null && employeePermission.AllowMultipleLogins == false && shifts.Any(shift => (string.Equals(shift.StaffId, this.Context.GetPrincipal().UserId, StringComparison.OrdinalIgnoreCase) || string.Equals(shift.CurrentStaffId, this.Context.GetPrincipal().UserId, StringComparison.OrdinalIgnoreCase)))) { throw new UserAuthorizationException(SecurityErrors.Microsoft_Dynamics_Commerce_Runtime_OpenMultipleShiftsNotAllowed, string.Format(CultureInfo.CurrentUICulture, "Permission denied to open multiple shifts: {0}", this.Context.GetPrincipal().UserId)); } if (request.IsShared) { if (!employeePermission.AllowManageSharedShift) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_EmployeeNotAllowedManageSharedShift, "Employee not allowed to manage shared shift."); } } } // Validate if shift is already open with given shift identifier. if (request.ShiftId != null && shifts.Any(shift => shift.ShiftId == request.ShiftId && string.Equals(shift.TerminalId, request.TerminalId, StringComparison.OrdinalIgnoreCase))) { throw new DataValidationException( DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_TerminalHasAnOpenShift, string.Format("There is already an open shift with shift id {0} on the current terminal.", request.ShiftId)); } // Validate if any shift is open for the cash drawer specified in request. bool cannotOpenShift = shifts.Any(shift => { bool cashDrawerHasOpenShift = string.Equals(shift.CashDrawer, request.CashDrawer, StringComparison.OrdinalIgnoreCase); return(cashDrawerHasOpenShift && (shift.IsShared || string.Equals(shift.CurrentTerminalId, request.TerminalId, StringComparison.OrdinalIgnoreCase))); }); if (cannotOpenShift) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CashDrawerHasAnOpenShift, "There is an open shift on the current cash drawer."); } }
/// <summary> /// Executes the resume shift workflow. /// </summary> /// <param name="request">The new shift request.</param> /// <returns>The resume shift response.</returns> protected override ResumeShiftResponse Process(ResumeShiftRequest request) { ThrowIf.Null(request, "request"); ThrowIf.Null(request.ShiftTerminalId, "request.ShiftTerminalId"); if (this.Context.GetTerminal() != null) { request.TerminalId = this.Context.GetTerminal().TerminalId; } bool includeSharedShifts = this.Permissions.HasManagerPrivileges || this.Permissions.AllowManageSharedShift || this.Permissions.AllowUseSharedShift; var staffId = this.Context.GetPrincipal().UserId; var terminalId = request.ShiftTerminalId; var shifts = ShiftDataDataServiceHelper.GetShifts( this.Context, this.Context.GetPrincipal().ChannelId, terminalId, request.ShiftId, includeSharedShifts); Shift shift = ShiftDataDataServiceHelper.FilterShifts(shifts, terminalId, staffId).FirstOrDefault(); this.ValidateCanResumeShift(request, shift); shift.CashDrawer = request.CashDrawer; shift.CurrentStaffId = this.Context.GetPrincipal().UserId; shift.CurrentTerminalId = request.TerminalId; shift.Status = ShiftStatus.Open; shift.StatusDateTime = this.Context.GetNowInChannelTimeZone(); UpdateShiftStagingTableDataRequest dataServiceRequest = new UpdateShiftStagingTableDataRequest(shift); request.RequestContext.Runtime.Execute <NullResponse>(dataServiceRequest, this.Context); return(new ResumeShiftResponse(shift)); }
/// <summary> /// Executes the workflow to get available Shifts. /// </summary> /// <param name="request">The request.</param> /// <returns>The response.</returns> protected override GetAvailableShiftsResponse Process(GetAvailableShiftsRequest request) { ThrowIf.Null(request, "request"); IEnumerable <Shift> shifts; EmployeePermissions employeePermission = EmployeePermissionHelper.GetEmployeePermissions(this.Context, this.Context.GetPrincipal().UserId); var staffId = this.Context.GetPrincipal().UserId; GetCurrentTerminalIdDataRequest dataRequest = new GetCurrentTerminalIdDataRequest(); string terminalId = this.Context.Execute <SingleEntityDataServiceResponse <string> >(dataRequest).Entity; bool isManager = this.Context.GetPrincipal().IsInRole(AuthenticationHelper.ManagerPrivilegies); bool readAllShifts; bool includeSharedShifts; switch (request.Status) { case ShiftStatus.Suspended: case ShiftStatus.BlindClosed: includeSharedShifts = employeePermission.AllowManageSharedShift; // If user is manager or has permission to logon multiple shifts or allowed to manage shared shifts) // Read all shifts including shared // Else read only shifts that belong to the user and are not shared shifts. if (isManager || (employeePermission.AllowMultipleShiftLogOn && includeSharedShifts)) { // Read all shifts shifts = ShiftDataDataServiceHelper.GetAllStoreShiftsWithStatus(this.Context, this.Context.GetPrincipal().ChannelId, request.Status, request.QueryResultSettings, true); } else if (employeePermission.AllowMultipleShiftLogOn && !includeSharedShifts) { shifts = ShiftDataDataServiceHelper.GetShiftsForStaffWithStatus(this.Context, this.Context.GetPrincipal().ChannelId, request.Status, request.QueryResultSettings, false); } else if (includeSharedShifts && !employeePermission.AllowMultipleShiftLogOn) { var allShifts = ShiftDataDataServiceHelper.GetShiftsForStaffWithStatus(this.Context, this.Context.GetPrincipal().ChannelId, request.Status, request.QueryResultSettings, true); // Exclude non shared shifts and shift not opened or used by the current staff id. shifts = allShifts.Where(s => (s.IsShared == true || s.CurrentStaffId == staffId || s.StaffId == staffId)); } else { shifts = ShiftDataDataServiceHelper.GetShiftsForStaffWithStatus(this.Context, this.Context.GetPrincipal().ChannelId, staffId, request.Status, request.QueryResultSettings, false); } break; case ShiftStatus.Open: includeSharedShifts = employeePermission.AllowManageSharedShift || employeePermission.AllowUseSharedShift; readAllShifts = isManager || (includeSharedShifts && employeePermission.AllowMultipleShiftLogOn); // If user is manager or (has permission to logon multiple shifts and allowed to manage or use shared shifts) // Read all terminal shifts including shared // Else read only shifts that belong to the user and are not shared shifts. if (readAllShifts) { var openShiftsOnTerminal = ShiftDataDataServiceHelper.GetAllOpenedShiftsOnTerminal(this.Context, this.Context.GetPrincipal().ChannelId, terminalId, false); var openSharedShiftsOnStore = ShiftDataDataServiceHelper.GetAllOpenedSharedShiftsOnStore(this.Context, this.Context.GetPrincipal().ChannelId); shifts = openShiftsOnTerminal.Union(openSharedShiftsOnStore); } else { IEnumerable <Shift> usableShifts; if (employeePermission.AllowMultipleShiftLogOn) { usableShifts = ShiftDataDataServiceHelper.GetAllOpenedShiftsOnTerminal(this.Context, this.Context.GetPrincipal().ChannelId, terminalId, false); } else { usableShifts = ShiftDataDataServiceHelper.GetOpenedShiftsOnTerminalForStaff(this.Context, this.Context.GetPrincipal().ChannelId, staffId, terminalId, false); } if (includeSharedShifts) { var openSharedShiftsOnStore = ShiftDataDataServiceHelper.GetAllOpenedSharedShiftsOnStore(this.Context, this.Context.GetPrincipal().ChannelId); shifts = usableShifts.Union(openSharedShiftsOnStore); } else { shifts = usableShifts; } } break; default: shifts = new Shift[] { }; break; } if (shifts != null || shifts.Count() != 0) { shifts = ShiftDataDataServiceHelper.FilterShifts(shifts, terminalId, staffId); } return(new GetAvailableShiftsResponse(shifts.AsPagedResult())); }
internal static IList <Shift> GetAllOpenedSharedShiftsOnStore(RequestContext context, long channelId) { return(ShiftDataDataServiceHelper.GetAllStoreShiftsWithStatus(context, channelId, ShiftStatus.Open, QueryResultSettings.AllRecords, true) .Where(s => s.IsShared).AsReadOnly()); }