/* eslint-disable camelcase */
import assign from "lodash/assign"
import find from "lodash/find"
import moment from "moment"
import client from "configure/client"
import membershipStatuses from "constants/membershipStatuses"
import membershipIds from "constants/membershipIds"
import PropType from "mixins/PropType"
import BaseModel from "../../BaseModel"
import WordpressModel from "../wordpress/model"
export const name = "users"
/**
* test
*
* @class UserModel
* @param {string} name | table name that will be used in all your queries
* @extends {BaseModel}
*/
class UserModel extends BaseModel {
constructor(props) {
super(name, UserModel.propTypes)
if (!props) return
this.props = { ...props }
this.error = this.validate(this.props)
this.initialized = true
}
/**
* reference to the wordpress member
* @type int
* @memberof UserModel
*/
get memberId() {
return this.props.memberId
}
set memberId(value) {
this.props.memberId = value
}
/**
* reference to the wordpress membership
* @type int
* @memberof UserModel
*/
get membershipId() {
return this.props.membershipId
}
set membershipId(value) {
this.props.membershipId = value
}
/**
* User's first name
* @type string
* @memberof UserModel
*/
get firstName() {
return this.props.firstName
}
set firstName(value) {
this.props.firstName = value
}
/**
* User's last name
* @type string
* @memberof UserModel
*/
get lastName() {
return this.props.lastName
}
set lastName(value) {
this.props.lastName = value
}
/**
* User's email address
* @type string|required
* @memberof UserModel
*/
get emailAddress() {
return this.props.emailAddress
}
set emailAddress(value) {
this.props.emailAddress = value
}
/**
* User's username referring to WP
* @type string|required
* @memberof UserModel
*/
get username() {
return this.props.username
}
set username(value) {
this.props.username = value
}
/**
* Registration date in wordpress
* @type date
* @memberof UserModel
*/
get registeredAt() {
return this.props.registeredAt
}
set registeredAt(value) {
this.props.registeredAt = value
}
/**
* Set and validates user properties
* @param {object} props | Properties of the UserModel object
*/
set(props) {
this.props = assign({}, this.props, props)
this.error = this.validate(this.props)
this.initialized = true
}
/**
* Selects the instances that match the given parameters
* @param {object} params | Parameters to filter the search
*/
find(params) {
return this.select(params)
}
/**
* Insert an instance with the validated properties
*/
create() {
return this.insert(this.props)
}
/**
* Update an instance with the validated properties
*/
update() {
const { id } = this.props
return this.updateById(id, this.props)
}
/**
* Checks if an instance exists based on the parameters passed
* @param {object} params | parameters for the search of the instance
*/
async exists(params) {
const result = await this.find(params).catch((error) => {
throw error
})
return !!result?.rows?.[0]
}
/**
* Validates the membership of a user
* @param {string} authorization | Bearer token found in the request header
*/
async validateMembership() {
if (!this.initialized) throw new Error("ERROR: Initialize user before validating it's membership")
if (this.error) return this.error
const admin = new WordpressModel()
const canLoginAsAdmin = await admin.login()
if (!canLoginAsAdmin) {
this.error = admin.error
return false
}
try {
const { emailAddress } = this.props
const result = await client.request({
method: "GET",
url: `/mp/v1/members?search=${emailAddress}&per_page=1`,
headers: {
Authorization: `Bearer ${admin.token}`,
"MEMBERPRESS-API-KEY": "xpdB3eRkAS",
},
})
const members = result?.data || []
const member = find(members, { email: emailAddress })
if (!member) {
this.error = "memeber_not_found"
return false
}
const activeMemberships = member?.active_memberships || []
let limitedAccess = false
let hasValidMembership = false
let activeMembership = null
for (let idx = 0; idx < activeMemberships.length; idx += 1) {
const membershipId = activeMemberships[idx]?.id
if (membershipId === membershipIds.employee) {
hasValidMembership = true
activeMembership = activeMemberships[idx]
break
}
const membership = find(
member?.recent_subscriptions,
{ membership: String(membershipId) },
)
const latestTransaction = find(
member?.recent_transactions,
{ membership: String(membershipId) },
)
if (membership?.status === membershipStatuses.active) {
if (membershipId === membershipIds.limitedAccess) {
limitedAccess = true
} else if (
membershipId !== membershipIds.onlineCoaching
&& membershipId !== membershipIds.coachingNEW
) {
hasValidMembership = true
activeMembership = membership || activeMemberships[idx]
break
}
} else if (!membership || membership?.status === membershipStatuses.cancelled) {
const today = moment()
const expirationDate = moment(latestTransaction?.expires_at)
if (today.isSameOrBefore(expirationDate)) {
hasValidMembership = true
activeMembership = membership || activeMemberships[idx]
}
}
}
this.set({
memberId: member?.id,
firstName: member?.first_name,
lastName: member?.last_name,
registeredAt: new Date(member?.registered_at),
})
if (!hasValidMembership) {
this.error = "membership_not_found"
await this.update().catch((error) => {
this.error = error
})
return false
}
this.set({ membershipId: Number(activeMembership?.id) })
await this.update().catch((error) => {
this.error = error
})
return {
...member,
hasValidMembership,
activeMembership,
limitedAccess,
}
} catch (error) {
return false
}
}
}
/**
* Defines the default properties types of the UserModel class
* @name propTypes
* @type object
* @constant
* @default
* @memberof UserModel
*/
UserModel.propTypes = {
memberId: PropType.number,
membershipId: PropType.number,
firstName: PropType.string,
lastName: PropType.string,
emailAddress: PropType.string().isRequired(),
registeredAt: PropType.string,
username: PropType.string().isRequired(),
}
export default UserModel