Example #1
0
            /// <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));
            }
Example #6
0
            /// <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());
 }