Blame view

apps/home/models/returns.js 21 KB
陈轩 authored
1 2 3 4 5 6 7
/**
 *  个人中心 退换货
 *  @author chenxuan <xuan.chen@yoho.cn>
 */

'use strict';
yyq authored
8
const _ = require('lodash');
yyq authored
9 10

// const path = require('path');
陈轩 authored
11
const Promise = require('bluebird');
yyq authored
12
const returnAPI = require('./returns-api');
hongweigao authored
13
const ordersAPI = require('./orders-api');
陈轩 authored
14
yyq authored
15 16
const pager = require(`${global.utils}/pager`).setPager;
陈轩 authored
17
// 使用 product中的分页逻辑
yyq authored
18 19
// const pagerPath = path.join(global.appRoot, '/apps/product/models/public-handler.js');
// const pager = require(pagerPath).handlePagerData;
陈轩 authored
20 21 22 23 24 25 26 27 28 29

const co = Promise.coroutine;
const api = global.yoho.API;
const helpers = global.yoho.helpers;

// 常量
const REFUND = 1; // 退货
const EXCHANGE = 2; // 换货
const TRUE = 'Y';
const RETURNS_EMPTY = '您没有退/换货订单';
yyq authored
30 31
const CANCEL_REFUND_URI = '/home/returns/cancelRefund';
const CANCEL_EXCHANGE_URI = '/home/returns/cancelChange';
陈轩 authored
32 33 34
const REFUND_URI = '/home/returns/refundDetail';
const EXCHANGE_URI = '/home/returns/exchangeDetail';
yyq authored
35
// 处理退换货商品链接
m  
OF1706 authored
36 37
const getProductUrlBySkc = (skn) => {
    // cnAlphabet = cnAlphabet || 'cnalphabet';
yyq authored
38
m  
OF1706 authored
39
    return helpers.getUrlBySkc(skn);
yyq authored
40
};
yyq authored
41
郝肖肖 authored
42 43 44 45 46 47 48 49 50 51
/**
 * 转换价格
 *
 * @param float|string $price 价格
 * @return float|string 转换之后的价格
 */
const transPrice = (price) => {
    return price ? (price * 1).toFixed(2) : '0.00';
};
yyq authored
52 53
const setDetailGoods = (list) => {
    let resData = [];
郝肖肖 authored
54
    let goods;
yyq authored
55 56

    _.forEach(list, value => {
郝肖肖 authored
57 58

        goods = {
59
            href: getProductUrlBySkc(value.product_skn),
郝肖肖 authored
60
            thumb: helpers.image(value.goods_image, 60, 60),
yyq authored
61
            name: value.product_name || '',
郝肖肖 authored
62 63 64
            color: value.color_name,
            size: value.size_name,
            yoho_coin_cut_num: value.yoho_coin_cut_num,
郝肖肖 authored
65 66
            real_pay_price: transPrice(value.real_pay_price),
            price: transPrice(value.sales_price),
郝肖肖 authored
67
            goods_type: value.goods_type,
yyq authored
68
            reason: value.reason_name
郝肖肖 authored
69 70 71
        };

        resData.push(goods);
yyq authored
72 73 74
    });

    return resData;
yyq authored
75 76
};
陈轩 authored
77 78
// 处理订单商品的数据
function getGoodsData(goods) {
yyq authored
79
    let arr = [];
陈轩 authored
80
陈轩 authored
81
    goods.forEach(good => {
yyq authored
82 83

        arr.push({
m  
OF1706 authored
84
            href: getProductUrlBySkc(good.product_skn),
yyq authored
85 86
            thumb: helpers.image(good.goods_image, 60, 60),
            name: good.product_name,
87
            goods_type: good.goods_type,
yyq authored
88 89 90
            color: good.color_name,
            size: good.size_name
        });
陈轩 authored
91 92 93 94 95 96
    });

    return arr;
}

/**
hongweigao authored
97 98 99 100 101
 * 获得快递列表
 * @return array
 */
const getExpressCompany = (expressList) => {
    let data = [];
hongweigao authored
102
hongweigao authored
103 104 105 106 107 108
    _.forEach(expressList, function(value) {
        data.push(value);
    });
    data = _.flatten(data);

    return data;
OF1706 authored
109
};
hongweigao authored
110 111

/**
陈轩 authored
112 113 114 115 116 117
 * 退换货列表页数据
 * @param  {string} uid   用户 uid
 * @param  {Number} page  当前页数
 * @param  {Number} limit 每页最大条数
 * @return {Object}             Promise
 */
yyq authored
118
const getReturnsList = co(function*(uid, page, limit) {
陈轩 authored
119 120
    page = Number.parseInt(page, 10) || 1;
    limit = Number.parseInt(limit, 10) || 10;
陈轩 authored
121
yyq authored
122
    let obj = {
陈轩 authored
123 124 125 126 127
        orders: [],
        pager: {}
    };
    let response = yield api.post('', {
        method: 'app.refund.getList',
yyq authored
128 129 130
        uid: uid,
        page: page,
        limit: limit
陈轩 authored
131 132 133 134 135
    });
    let repData = response.data;

    // 处理数据
    if (response.code === 200 && repData && repData.list.length) {
yyq authored
136 137 138 139 140
        obj.pager = Object.assign({
            count: repData.total,
            curPage: page,
            totalPages: repData.total_page || 1
        }, pager(repData.total_page, {page: page}));
陈轩 authored
141 142

        repData.list.forEach(item => {
yyq authored
143 144 145
            let t = {
                returnId: item.id,
                orderNum: item.order_code,
hongweigao authored
146
                orderTime: item.order_create_time,
yyq authored
147 148 149
                returnTime: item.create_time,
                returnStatus: item.status_name
            };
陈轩 authored
150
yyq authored
151 152
            let canCancel = item.canCancel === TRUE;
            let isChange, uri = '', cancelUri = '';
陈轩 authored
153 154 155 156

            switch (item.refund_type) {
                case REFUND:
                    isChange = false;
yyq authored
157 158
                    uri = REFUND_URI;
                    cancelUri = CANCEL_REFUND_URI;
陈轩 authored
159 160 161
                    break;
                case EXCHANGE:
                    isChange = true;
yyq authored
162 163
                    uri = EXCHANGE_URI;
                    cancelUri = CANCEL_EXCHANGE_URI;
陈轩 authored
164 165
                    break;
                default:
yyq authored
166
                    break;
陈轩 authored
167 168
            }
yyq authored
169 170 171 172 173 174 175
            Object.assign(t, {
                isChange: isChange,
                canCancel: canCancel,
                canCancelUrl: cancelUri,
                moreHref: helpers.urlFormat(uri, { id: item.id }),
                goods: getGoodsData(item.goods)
            });
陈轩 authored
176 177 178 179 180 181 182 183 184

            obj.orders.push(t);
        });
    } else {
        obj.empty = RETURNS_EMPTY;
    }

    return obj;
});
陈轩 authored
185
hongweigao authored
186 187 188 189 190 191
/**
 * 退货申请页数据
 * @param $orderCode
 * @param $uid
 * @return array|mixed
 */
yyq authored
192 193 194 195 196 197 198 199
const getOrderRefund = (orderCode, uid) => {
    let process = function*() {
        let resData = {};
        let result = yield returnAPI.getRefundGoodsAsync(orderCode, uid);

        if (result.data) {
            let goods = [];
            let returnReason = result.data.return_reason,
郝肖肖 authored
200
                remarks = _.split(_.get(result, 'data.special_notice.remark', ''), '   ', 2); // 使用3个空格拆分
yyq authored
201 202 203 204


            _.forEach(_.get(result, 'data.goods_list', []), value => {
                let item = {
m  
OF1706 authored
205
                    href: getProductUrlBySkc(value.product_skn),
hongweigao authored
206
                    thumb: helpers.image(value.goods_image, 60, 60),
yyq authored
207
                    name: value.product_name,
hongweigao authored
208
                    color: value.factory_color_name,
yyq authored
209
                    size: value.size_name,
210
                    price: transPrice(value.last_price),
yyq authored
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
                    skn: value.product_skn,
                    skc: value.product_skc,
                    sku: value.product_sku,
                    goods_type_id: value.goods_type_id,
                    goods_type: value.goods_type,
                    reason: returnReason
                };

                // tar note 为每个特殊商品都添加标识
                if (value.is_limit_skn === 'Y') {
                    item.specialNoticeBo = {
                        title: _.get(result, 'data.special_notice.title', ''),
                        remark1: remarks[0] || '',
                        remark2: remarks[1] || ''
                    };

                    // tar note 对数组做处理,为不显示的添加 inactive
hongweigao authored
228 229
                    if (_.get(result, 'data.special_return_reason')) {
                        let spReason = _.get(result, 'data.special_return_reason');
yyq authored
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247

                        _.forEach(item.reason, (subVal, subKey) => { // eslint-disable-line
                            if (_.indexOf(spReason, subKey)) {
                                _.set(item, `reason[${subKey}].inactive`, true);
                            }
                        });
                    }
                }

                goods.push(item);

                // 商品中有鞋类,传给前端标识
                if (value.hasShoes) {
                    _.set(resData, 'tips.footwear', true);
                }
            });

            Object.assign(resData, {
yyq authored
248
                goods: goods,
郝肖肖 authored
249
                orderCode: orderCode
yyq authored
250 251 252 253 254 255 256 257
            });

            _.forEach(result.data.return_amount_mode, (val, key) => {
                if (val.is_default === 'Y') {
                    _.set(result, `data.return_amount_mode[${key}].default`, true);
                }
            });
hongweigao authored
258
            resData.returnBankMode = _.get(result, 'data.return_bank_mode', '');
yyq authored
259 260 261
            resData.returnAmountMode = result.data.return_amount_mode;
        }
hongweigao authored
262
        return {refund: resData};
yyq authored
263 264 265 266
    };

    return co(process)();
};
陈轩 authored
267
268
/**
hongweigao authored
269 270 271 272 273 274 275 276 277 278
 * 提交退货申请
 * @param $orderCode
 * @param $uid
 * @param array $goods
 * @param array $payment
 * @return array|mixed
 */
const saveRefund = (req, uid) => {
    let process = function*() {
        let orderCode = req.body.orderCode,
hongweigao authored
279 280
            goods = req.body.goods,
            payment = req.body.payment;
hongweigao authored
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309


        if (_.isEmpty(orderCode) || orderCode < 1 ||
            _.isEmpty(goods) || _.isEmpty(payment)) {
            return {
                code: 203,
                message: '非法提交'
            };
        }

        // 调用模型提交退货申请
        let order = yield ordersAPI.viewOrderData(orderCode, uid);

        if (_.isEmpty(order)) {
            return {
                code: 403,
                message: '没有找到该订单'
            };
        }

        // 组装站内信内容
        let title = '您有一笔订单提交退货申请:';
        let content = '您的订单' + orderCode + '申请退货,给您带来不便敬请谅解!请至订单中心查看详情!';

        // 调用接口保存退货申请
        let result = yield returnAPI.refundSubmit(orderCode, uid, goods, payment);

        if (_.get(result, 'code') === 200) {
            // 退货成功发送站内信
hongweigao authored
310 311
            returnAPI.sendMessage(uid, title, content);
hongweigao authored
312 313 314 315 316 317 318 319 320 321
            result.data.refer = helpers.urlFormat('/home/returns/refundSuccess', {orderCode: orderCode});
        }

        return result;
    };

    return co(process)();
};

/**
322 323 324 325 326
 * 获取退货详情页数据
 * @param $uid
 * @param $id
 * @return array|mixed
 */
yyq authored
327 328 329 330 331 332 333 334 335 336 337 338
const getRefundDetail = (applyId, uid) => {
    let process = function*() {
        let resData = {};
        let result = yield Promise.all([
            returnAPI.getRefundDetailAsync(applyId, uid),
            returnAPI.getExpressCompanyAsync()
        ]);

        if (result[0].data) {
            let data = result[0].data;
            let detail = {
                isChange: false,
hongweigao authored
339
                returnId: applyId,
yyq authored
340 341 342 343 344
                orderNum: data.source_order_code,
                nowStatus: data.status_name,
                applyTime: data.create_time,
                payMode: data.source_payment_type_desc || '',
                backMode: data.return_amount_mode_name || '',
郝肖肖 authored
345 346
                return_asset_desc: data.return_asset_desc,
                return_amount: data.return_amount,
yyq authored
347 348 349 350 351 352 353
                goods: setDetailGoods(data.goods_list)
            };

            if (+data.status !== 0) {
                detail.express = {
                    id: _.get(data, 'notice.express_id', ''),
                    company: _.get(data, 'notice.express_company', ''),
郝肖肖 authored
354
                    number: _.get(data, 'notice.express_number', ''),
郝肖肖 authored
355
                    title: _.get(data, 'notice.title', '')
yyq authored
356 357 358 359 360 361 362 363 364 365 366 367
                };
            }

            detail.statusList = [];
            _.forEach(data.statusList, value => {
                detail.statusList.push({
                    name: value.name,
                    act: value.act === 'Y'
                });
            });

            if (data.canCancel === 'Y') {
郝肖肖 authored
368
                detail.canCancelUrl = '/home/returns/cancelRefund';
yyq authored
369 370 371 372 373 374
            }

            resData.detail = detail;

        }
375
        if (result[1].data && resData.detail && resData.detail.express) {
hongweigao authored
376
            _.set(resData, 'detail.express.expressList', getExpressCompany(result[1].data));
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
        }

        return resData;
    };

    return co(process)();
};

/**
 * 获取换货详情页数据
 * @param $uid
 * @param $id
 * @return array|mixed
 */
const getChangeDetail = (applyId, uid) => {
    let process = function*() {
        let resData = {};
        let result = yield Promise.all([
            returnAPI.getChangeDetailAsync(applyId, uid),
            returnAPI.getExpressCompanyAsync()
        ]);

        if (result[0].data) {
            let data = result[0].data;
            let detail = {
                isChange: true,
hongweigao authored
403
                returnId: applyId,
404 405 406 407 408 409 410 411 412 413 414
                orderNum: data.source_order_code,
                nowStatus: data.status_name,
                applyTime: data.create_time,
                goods: setDetailGoods(data.goods_list)
            };

            if (+data.status !== 0 && +data.delivery_tpye !== 20) {
                detail.express = {
                    id: _.get(data, 'notice.express_id', ''),
                    company: _.get(data, 'notice.express_company', ''),
                    number: _.get(data, 'notice.express_number', ''),
郝肖肖 authored
415
                    expressDeadLine: _.get(data, 'notice.date', ''),
郝肖肖 authored
416
                    title: _.get(data, 'notice.title', '')
417 418 419 420 421 422 423 424 425 426 427 428
                };
            }

            detail.statusList = [];
            _.forEach(data.statusList, value => {
                detail.statusList.push({
                    name: value.name,
                    act: value.act === 'Y'
                });
            });

            if (data.canCancel === 'Y') {
hongweigao authored
429
                detail.canCancelUrl = helpers.urlFormat('/home/returns/cancelChange');
430 431 432 433 434 435
            }

            resData.detail = detail;

        }
436
        if (result[1].data && resData.detail && resData.detail.expressList) {
hongweigao authored
437
            _.set(resData, 'detail.express.expressList', getExpressCompany(result[1].data));
yyq authored
438 439 440 441 442 443 444 445
        }

        return resData;
    };

    return co(process)();
};
hongweigao authored
446
/**
OF1706 authored
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
 * 提交换货申请
 * @param $orderCode
 * @param $uid
 * @param $goods
 * @param $consigneeName
 * @param $areaCode
 * @param $address
 * @param $mobile
 * @param $zipCode
 * @param $deliveryType
 * @return array|mixed
 */
const saveExchange = (req, uid) => {
    let process = function*() {

        let orderCode = req.body.orderCode,
            goods = req.body.goods,
            consigneeName = req.body.consigneeName,
            areaCode = req.body.areaCode,
            address = req.body.address,
            mobile = req.body.mobile,
            zipCode = req.body.zipCode,
            deliveryType = req.body.deliveryType;

        if (_.isEmpty(orderCode) || orderCode < 1 || _.isEmpty(goods) ||
            _.isEmpty(deliveryType) || _.isEmpty(consigneeName) || _.isEmpty(areaCode) ||
            _.isEmpty(address) || _.isEmpty(mobile)) {
            return {
                code: 203,
                message: '非法提交'
            };
        }

        // 调用接口查询订单详情
        let order = yield ordersAPI.viewOrderData(orderCode, uid);

        if (_.isEmpty(order)) {
            return {
                code: 403,
                message: '没有找到该订单'
            };
        }

        // 订单15天后不能换货
        // if (_.get(order, 'code') === 200) {
        //     if ((new Date() - order.data.create_time) > 15*86400) {
        //         return {
        //             code: 400,
        //             message: '您的订单已经超过了换货有效期'
        //         }
        //     }
        // }

        // 保存换货申请
        let result = yield returnAPI.exchangeSubmit(orderCode, goods, consigneeName, areaCode,
            address, mobile, zipCode, deliveryType, uid);

        // 组装站内信内容
        let title = '您有一笔订单提交换货申请:';
        let content = '您的订单' + orderCode + '申请换货,给您带来不便敬请谅解!请至订单中心查看详情!';

        // 换货成功,返回前端相应格式,并返回换货成功页跳转链接
        if (_.get(result, 'code') === 200) {
            // 换货成功发送站内信
            returnAPI.sendMessage(uid, title, content);
            result.data.refer = helpers.urlFormat('/home/returns/exchangeSuccess', {orderCode: orderCode});
        }

        return result;
    };

    return co(process)();
};

/**
hongweigao authored
522 523 524 525 526
 * 换货申请页数据
 * @param $orderCode
 * @param $uid
 * @return array|mixed
 */
yyq authored
527 528 529 530 531 532 533 534
const getOrderExchange = (orderCode, uid) => {
    let process = function*() {
        let resData = {};
        let result = yield returnAPI.getExchangeGoodsAsync(orderCode, uid);

        if (result.data) {
            let goods = [];
            let sknPromise = [];
hongweigao authored
535
            let returnReason = result.data.exchange_reason,
yyq authored
536 537 538 539
                remarks = _.split(_.get(result, 'data.special_notice.remark', ''), '   ', 2); // 使用3个空格拆分

            _.forEach(_.get(result, 'data.goods_list', []), value => {
                let item = {
OF1706 authored
540
                    href: getProductUrlBySkc(value.product_skn),
hongweigao authored
541
                    thumb: helpers.image(value.goods_image, 60, 60),
yyq authored
542 543 544
                    name: value.product_name,
                    color: value.color_name,
                    size: value.size_name,
545
                    price: value.last_price,
yyq authored
546 547 548 549
                    skn: value.product_skn,
                    skc: value.product_skc,
                    sku: value.product_sku,
                    goods_type_id: value.goods_type_id,
550
                    goods_type: value.goods_type,
551
                    reason: _.cloneDeep(returnReason)
yyq authored
552 553 554 555 556
                };

                // tar note 为每个特殊商品都添加标识
                if (value.is_limit_skn === 'Y') {
                    item.specialNoticeBo = {
hongweigao authored
557
                        title: _.get(result, 'data.specialNoticeBo.title', ''),
yyq authored
558 559 560 561
                        remark1: remarks[0] || '',
                        remark2: remarks[1] || ''
                    };
562
                    let spReason = _.get(result, 'data.special_exchange_reason', []);
yyq authored
563
564 565 566 567 568
                    // tar note 对数组做处理,为不显示的添加 inactive
                    if (spReason && spReason.length) {
                        _.forEach(item.reason, subVal => { // eslint-disable-line
                            if (!_.filter(spReason, ['id', subVal.id]).length) {
                                subVal.inactive = true;
yyq authored
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
                            }
                        });
                    }
                }

                goods.push(item);

                // 商品中有鞋类,传给前端标识
                if (value.hasShoes) {
                    _.set(resData, 'tips.footwear', true);
                }

                sknPromise.push(returnAPI.getProductDataAsync(value.product_skn));
            });

            Object.assign(resData, {
                orderCode: orderCode,

                // 换货地址相关数据(邮编为可空参数)
                name: _.get(result, 'data.address.consignee', ''),
                area: _.get(result, 'data.address.area', ''),
                area_code: _.get(result, 'data.address.area_code', ''),
                address: _.get(result, 'data.address.address', ''),
                phone: _.get(result, 'data.address.mobile', ''),
                postcode: _.get(result, 'data.address.zip_code', '')
            });
hongweigao authored
596
            let productList = yield Promise.all(sknPromise);
yyq authored
597
hongweigao authored
598
            _.forEach(productList, (product, key) => { // 遍历得到每件商品
OF1706 authored
599
hongweigao authored
600 601
                let colorSize = [],
                    value = product.data;
yyq authored
602 603

                _.forEach(value.goods_list, val => { // 遍历商品得到每个颜色
OF1706 authored
604
yyq authored
605
                    let size = [];
OF1706 authored
606
yyq authored
607 608 609 610 611 612 613 614
                    _.forEach(val.size_list, v => { // 遍历颜色得到每个尺码
                        if (+v.storage_number > 0) { // 当某个尺码下有库存时,将该颜色及其对应的尺码加入该商品选项下
                            size.push(v);
                        }
                    });

                    if (size.length) {
                        colorSize.push({
hongweigao authored
615
                            color: val.factory_goods_name,
yyq authored
616 617
                            colorId: val.color_id,
                            goodsId: val.goods_id,
yyq authored
618
                            skc: val.product_skc,
yyq authored
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
                            sizeList: size
                        });
                    }
                });

                if (colorSize.length) {
                    goods[key].colorSize = colorSize;
                } else {
                    goods[key].banMsg = '库存不足不能换货';
                }

            });

            resData.goods = goods;
        }
hongweigao authored
635
        return {exchange: resData};
yyq authored
636 637 638 639 640
    };

    return co(process)();
};
OF1706 authored
641 642 643 644 645 646
const getDelivery = (areaCode, uid, gender, channel) => {
    return returnAPI.getDeliveryAsync(areaCode, uid, gender, channel).then((result) => {
        return result;
    });
};
OF1706 authored
647 648 649 650 651 652 653 654 655 656 657 658
const getCancelRefund = (id, uid) => {
    return returnAPI.cancelRefundAsync(id, uid).then((result) => {
        return result;
    });
};

const getCancelChange = (id, uid) => {
    return returnAPI.cancelChangeAsync(id, uid).then((result) => {
        return result;
    });
};
OF1706 authored
659
const setExpressNumber = (id, expressId, expressNumber, uid, expressCompany, isChange) => {
OF1706 authored
660
    return returnAPI.setExpressNumberAsync(id, expressId, expressNumber, uid, expressCompany, isChange).then((result) => { // eslint-disable-line
OF1706 authored
661 662 663 664
        return result;
    });
};
郝肖肖 authored
665 666 667 668
const refundCompute = (uid, orderCode, goods) => {
    return returnAPI.refundComputeAsync(uid, orderCode, goods);
};
yyq authored
669
module.exports = {
hongweigao authored
670 671 672 673
    getReturnsList,         // 我的订单,退换货列表
    getOrderRefund,         // 我的订单,申请退货
    saveRefund,             // 退货提交
    getRefundDetail,        // 退货详情
OF1706 authored
674
    saveExchange,           // 换货提交
hongweigao authored
675 676
    getChangeDetail,        // 换货详情
    getOrderExchange,       // 我的订单,申请换货
OF1706 authored
677
    getDelivery,            // 获取换货方式
OF1706 authored
678 679
    getCancelRefund,        // 取消退货申请
    getCancelChange,        // 取消换货申请
郝肖肖 authored
680
    setExpressNumber,       // 设置快递
郝肖肖 authored
681
    refundCompute          // 退货结算
陈轩 authored
682
};