Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't break out orders with quantities #2119

Merged
merged 14 commits into from
Apr 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions imports/plugins/core/orders/client/components/lineItems.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class LineItems extends Component {
<div className="order-items">
<div
className="invoice order-item form-group order-summary-form-group"
onClick={() => handleClick(uniqueItem.cartItemId)}
onClick={() => handleClick(uniqueItem._id)}
style={{ height: 70 }}
>

Expand All @@ -42,7 +42,7 @@ class LineItems extends Component {
</div>

<div className="order-detail-quantity">
{quantity || 1}
{quantity || uniqueItem.quantity}
</div>

<div className="order-detail-price">
Expand All @@ -56,7 +56,7 @@ class LineItems extends Component {
);
}

renderLineItemInvoice(uniqueItem, shippingRate, quantity) {
renderLineItemInvoice(uniqueItem) {
return (
<div>
<div className="order-summary-form-group">
Expand All @@ -69,14 +69,14 @@ class LineItems extends Component {
<div className="order-summary-form-group">
<strong><Translation defaultValue="Shipping" i18nKey="cartSubTotals.shipping"/></strong>
<div className="invoice-details">
{formatPriceString(shippingRate)}
{formatPriceString(uniqueItem.shipping.rate)}
</div>
</div>

<div className="order-summary-form-group">
<strong>Item tax</strong>
<div className="invoice-details">
{uniqueItem.taxDetail ? formatPriceString(uniqueItem.taxDetail.tax / quantity) : formatPriceString(0)}
{uniqueItem.taxDetail ? formatPriceString(uniqueItem.taxDetail.tax / uniqueItem.quantity) : formatPriceString(0)}
</div>
</div>

Expand All @@ -92,10 +92,10 @@ class LineItems extends Component {
<div className="invoice-details">
{uniqueItem.taxDetail ?
<strong>
{this.calculateTotal(uniqueItem.variants.price, shippingRate, uniqueItem.taxDetail.tax)}
{this.calculateTotal(uniqueItem.variants.price, uniqueItem.shipping.rate, uniqueItem.taxDetail.tax)}
</strong> :
<strong>
{this.calculateTotal(uniqueItem.variants.price, shippingRate, 0)}
{this.calculateTotal(uniqueItem.variants.price, uniqueItem.shipping.rate, 0)}
</strong>
}
</div>
Expand All @@ -107,22 +107,21 @@ class LineItems extends Component {

render() {
const { uniqueItems, isExpanded, onClose } = this.props;

return (
<div>
{uniqueItems.map((uniqueItem) => {
if (!isExpanded(uniqueItem.cartItemId)) {
if (!isExpanded(uniqueItem._id)) {
return (
<div key={uniqueItem.cartItemId}> { this.renderLineItem(uniqueItem.items[0], uniqueItem.items.length) } </div>
<div key={uniqueItem._id}> { this.renderLineItem(uniqueItem) } </div>
);
}

return (
<div className="roll-up-invoice-list" key={uniqueItem.cartItemId}>
<div className="roll-up-invoice-list" key={uniqueItem._id}>
<div className="roll-up-content">

<div style={{ float: "right" }}>
<button className="rui btn btn-default flat icon-only" onClick={() => onClose(uniqueItem.cartItemId)}>
<button className="rui btn btn-default flat icon-only" onClick={() => onClose(uniqueItem._id)}>
<i
className="rui font-icon fa-lg fa fa-times"
/>
Expand All @@ -131,12 +130,12 @@ class LineItems extends Component {

<br/><br/>

{uniqueItem.items.map((item) => (
<div key={item._id}>
{ this.renderLineItem(item) }
{ this.renderLineItemInvoice(item, uniqueItem.shippingRate, uniqueItem.items.length) }
{[...Array(uniqueItem.quantity)].map((v, i) =>
<div key={i}>
{ this.renderLineItem(uniqueItem, 1) }
{ this.renderLineItemInvoice(uniqueItem) }
</div>
))}
)}

</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class LineItemsContainer extends Component {

render() {
const { invoice, uniqueItems } = this.props;

return (
<TranslationProvider>
<LineItems
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,16 +309,13 @@ Template.coreOrderShippingInvoice.helpers({
refundAmount() {
return Template.instance().refundAmount;
},
/**
* Discount
* @return {Number} current discount amount
*/

invoice() {
const instance = Template.instance();
const order = instance.state.get("order");

const invoice = Object.assign({}, order.billing[0].invoice, {
totalItems: order.items.length
totalItems: _.sumBy(order.items, (o) => o.quantity)
});
return invoice;
},
Expand Down Expand Up @@ -479,12 +476,10 @@ Template.coreOrderShippingInvoice.helpers({
const currentData = Template.currentData();
const shipment = currentData.fulfillment;

// returns array of individual items that have been checked out
const returnItems = _.map(shipment.items, (item) => {
const originalItem = _.find(order.items, {
_id: item._id
});
return _.extend(originalItem, item);
// returns order items with shipping detail
const returnItems = _.map(order.items, (item) => {
const shipping = shipment.shipmentMethod;
return _.extend(item, { shipping });
});

let items;
Expand All @@ -495,43 +490,13 @@ Template.coreOrderShippingInvoice.helpers({

items = _.map(returnItems, (item) => {
const taxDetail = _.find(taxes, {
lineNumber: item.cartItemId
lineNumber: item._id
});
return _.extend(item, { taxDetail });
});
} else {
items = returnItems;
}

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need more comments, not less.

* It goes through individual items and groups similar items using the cartItemId.
* The output is an object whose keys are cartItemId and every item with the same
* cartItemId is added as a value
*/
let uniqueItems = items.reduce((carts, item) => {
let cart;

if (carts[item.cartItemId]) {
cart = carts[item.cartItemId];
cart = Object.assign({}, cart, {
items: [...cart.items, item]
});
} else {
cart = {
cartItemId: item.cartItemId,
productId: item.productId,
shippingRate: shipment.shipmentMethod.rate,
items: [item]
};
}

carts[item.cartItemId] = cart;
return carts;
}, {});

// Converts the uniqueItems object to an array
uniqueItems = Object.keys(uniqueItems).map(k => uniqueItems[k]);

return uniqueItems;
return items;
}
});
5 changes: 3 additions & 2 deletions imports/plugins/included/inventory/server/hooks/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function markInventoryShipped(doc) {
const cartItems = [];
for (const orderItem of orderItems) {
const cartItem = {
_id: orderItem.cartItemId,
_id: orderItem.cartItemId || orderItem._id,
shopId: orderItem.shopId,
quantity: orderItem.quantity,
productId: orderItem.productId,
Expand All @@ -112,9 +112,10 @@ function markInventoryShipped(doc) {
function markInventorySold(doc) {
const orderItems = doc.items;
const cartItems = [];
// If a cartItemId exists it's a legacy order and we use that
for (const orderItem of orderItems) {
const cartItem = {
_id: orderItem.cartItemId,
_id: orderItem.cartItemId || orderItem._id,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change / behaviour documented elsewhere? Should be added to release docs?

shopId: orderItem.shopId,
quantity: orderItem.quantity,
productId: orderItem.productId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint camelcase: 0 */
import _ from "lodash";
import { Meteor } from "meteor/meteor";
import { SimpleSchema } from "meteor/aldeed:simple-schema";
import { Packages } from "/lib/collections";
Expand Down
3 changes: 1 addition & 2 deletions server/methods/core/cart-create.app-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ describe("Add/Create cart methods", function () {
return done();
});

it("should throw an error if order creation has failed", function (done) {
it("should throw an error if order creation has failed", function () {
const cart = Factory.create("cartToOrder");
spyOnMethod("copyCartToOrder", cart.userId);
// The main moment of test. We are spy on `insert` operation but do not
Expand All @@ -196,7 +196,6 @@ describe("Add/Create cart methods", function () {
}
expect(copyCartFunc).to.throw(Meteor.Error, /Invalid request/);
expect(insertStub).to.have.been.called;
return done();
});

it("should create an order", function (done) {
Expand Down
61 changes: 18 additions & 43 deletions server/methods/core/cart.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,12 @@ Meteor.methods({
const order = Object.assign({}, cart);
const sessionId = cart.sessionId;

if (!order.items || order.items.length === 0) {
const msg = "An error occurred saving the order. Missing cart items.";
Logger.error(msg);
throw new Meteor.Error("no-cart-items", msg);
}

Logger.debug("cart/copyCartToOrder", cartId);
// reassign the id, we'll get a new orderId
order.cartId = cart._id;
Expand Down Expand Up @@ -590,58 +596,27 @@ Meteor.methods({
};
}

order.billing[0].currency.exchangeRate = exchangeRate;


const expandedItems = [];

// init item level workflow
_.each(order.items, function (item) {
// Split items based on their quantity
for (let i = 0; i < item.quantity; i++) {
// Clone Item
const itemClone = _.clone(item);

// Remove the quantity since we'll be expanding each item as
// it's own record
itemClone.quantity = 1;

itemClone._id = Random.id();
itemClone.cartItemId = item._id; // used for transitioning inventry
itemClone.workflow = {
status: "new"
};

expandedItems.push(itemClone);

// Add each item clone to the first shipment
if (order.shipping[0].items) {
order.shipping[0].items.push({
_id: itemClone._id,
productId: itemClone.productId,
shopId: itemClone.shopId,
variantId: itemClone.variants._id
});
}
_.each(order.items, (item) => {
if (order.shipping[0].items) {
order.shipping[0].items.push({
_id: item._id,
productId: item.productId,
shopId: item.shopId,
variantId: item.variants._id
});
}
});

// Replace the items with the expanded array of items
order.items = expandedItems;
order.shipping[0].items.packed = false;
order.shipping[0].items.shipped = false;
order.shipping[0].items.delivered = false;

if (!order.items || order.items.length === 0) {
const msg = "An error occurred saving the order. Missing cart items.";
Logger.error(msg);
throw new Meteor.Error("no-cart-items", msg);
}

// set new workflow status
order.billing[0].currency.exchangeRate = exchangeRate;
order.workflow.status = "new";
order.workflow.workflow = ["coreOrderWorkflow/created"];

// insert new reaction order
const orderId = Collections.Orders.insert(order);
Logger.info("Created orderId", orderId);

if (orderId) {
Collections.Cart.remove({
Expand Down